Reputation: 88378
I have a directory with zero or more files with names like
on_common_20131020.xml
on_common_20131021.xml
on_common_20131022.xml
and so on. In order to extract the datestamp of the most recent one, I know I can use the following hack
ls -rt on_common* | tail -n 1 | egrep -o '[0-9]{8}'
(though if there is a better way I'd love to know). Now the thing is, I want to capture this value in a script, so I have the following line:
RECENT=$(ls -rt on_common* | tail -n 1 | egrep -o '[0-9]{8}')
However, there may not be any such files in the directory, in which case ls
will fail, and I want the value of RECENT to be, in that case, 00010101. I know how to use ' c1 || c2' to execute command c2 if and only if command c1 fails, but was unable to find anything that would give me the equivalent of this pseudo-Bash:
RECENT=$(ls -rt on_common* | tail -n 1 | egrep -o '[0-9]{8}') || '00010101' # WRONG
Yes I can do this with if
...fi
, but is there a single expression form?
EDIT
It turns out there was just a missing echo. The Bash syntax says:
A list is a sequence of one or more pipelines separated by one of the operators ‘;’, ‘&’, ‘&&’, or ‘||’, and optionally terminated by one of ‘;’, ‘&’, or a newline.
So I was close in that pipelines can be separated by ||
but the expression to the right of the ||
was not a pipeline (it wasn't even a command).
And another pedantic note for anyone that ends up here. Using -t
in ls
when there is a datestamp in the filename is pretty dangerous; someone could touch a filename with a datesamp in it. I ended up with:
RECENT=$(ls -1 on_common* 2>/dev/null | sort -r | egrep -om1 '[0-9]{8}' || echo '00010101')
which is a combination of Blue Moon's (redirect to dev/null) and jaap's answer (lack on inner parentheses and -m for egrep).
Upvotes: 2
Views: 116
Reputation: 3838
You could use a sub-shell like this :
command1 |(command2 || <treatment if command2 fails>)
var=$(command1 |(command2 || <treatment if command2 fails>)) # to get the commands suite output in a variable
And if you want execute treatment only if command1 fails :
(command1 || <treatment if command1 fails>)|command2
var=$((command1 || <treatment if command1 fails>)|command2) # to get the commands suite output in a variable
Upvotes: 0
Reputation: 5959
First, your search expression can be a bit shorter
ls -t on_common* | egrep -om1 '[0-9]{8}'
For the second part, this should work
RECENT=$(ls -t on_common* | egrep -om1 '[0-9]{8}' || echo "0001-01-01")
Upvotes: 1
Reputation: 121347
RECENT=$((ls -rt on_common* 2>/dev/null| tail -n 1 | egrep -o '[0-9]{8}')
|| echo '0001-01-01')
will do the equivalent of c1 || c2
as you desired.
Note that I redirected stderr to /dev/null ( 2>/dev/null
) in case ls
fails. If do you want to see the error, you can remove it.
Upvotes: 2