开发者

Interpreting shell commands within Bash if/else statements

While trying to make a conditional statement to check the amount of fi开发者_Python百科les in a directory, I have stumbled upon a problem. My initial way of writing this script:

ELEM=`ls -l $DIR | wc -l` 
if [ $ELEM -lt 5 ] ; then

works. However I want to move my $ELEM into the conditional parameter block so it can be interpreted when I reach that if statement. I have tried playing around with different combinations of single quotes, double quotes, back ticks, and parentheses.

Does anyone know how to solve this problem?


Never use ls in batch mode, use globbing instead. Also avoid backquotes, unquoted variables, and the [ builtin:

shopt -s nullglob  # expand to an empty array if directory is empty
shopt -s dotglob   # also glob dotfiles
files=("$DIR"/*)
count=${#files[@]}
if ((count > 5))
then
  ...
fi


For some reason it didn't occur to me until just now to use this:

ELEM="`ls -l $DIR | wc -l`"

Thanks for your time.


What you seem to want to be able to do is something that C allows:

if (elem = countfiles(dir) < 5)

Bash can do it like this:

if (( (elem = $(ls "$DIR" 2>/dev/null | wc -l) ) < 5))

Or you could create a function called countfiles and use it like this:

if (( ( elem = $(countfile "$DIR") ) < 5))

where the function might be something like:

countfiles() {
    find "$1" -maxdepth 1 -type f | wc -l
}


Most of the solutions posted so far are (IMHO) overcomplicated. As long as the ls command on your system supports the -B option (display special characters as octal escape sequences), you can just use:

if [[ $(ls -B "$DIR" | wc -l) -lt 5 ]]; then

Note that while parsing ls is generally a bad idea, in this case all we're trying to do is find the number of listings, so there's a lot less to go wrong than usual. In fact, the only thing that wc -l cares about is the number of lines, so the only thing that could go wrong is that a filename might have a newline in it, and hence be mistaken for two filenames; using the -B option to ls protects against this, so it winds up being safe (at least as far as I can see).


Improved countfiles function (which doesn't get confused by newlines in file names):

countfiles() {
   find "$1" -maxdepth 1 -type f -print0 | tr -dc '\0' | wc -c
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜