Reputation: 119
I have potentially a large number of generated files and subdirectories in a directory for which the number is not known ahead of execution. For simplicity, lets say I just want to invoke
mv * /another_dir/.
But for large numbers of files and subdirectories, it'll come back with the dreaded 'argument too long'. Yes I know find and xargs is a way to deal with it. But I want to test that number against ARG_MAX and try it that way first.
I'm on a Mac and so I can't up the ulimit setting.
So far I have
# max_value
if ((expr `getconf ARG_MAX` - `env|wc -c` - `env|wc -l` \* 4 - 2048) ) ; then echo "ok" ; fi
which offers me a value to test against.
Lets say my test value to compute number of files or subdirectories in directory is based on
# test_value
(find . -maxdepth 1 | wc -l)
How can I get a working expression no matter how many files
if (test_value < max_value ) ; then echo "do this" else echo "do that" ; fi
Every way I try to construct the if test, the syntax fails for some reason in trying to set the max_value and test_value parameters and then test them together. Grateful for help.
Upvotes: 0
Views: 185
Reputation: 125948
When writing shell scripts, you have to pay a lot of attention to what context you're in, and use the right syntax for that context. The thing that goes between if
and then
is treated as a command, so you could use e.g. if expr 2 \> 1; then
. But the modern replacement of the expr
command is the (( ))
arithmetic expression, so you'd use if (( 2 > 1 )); then
. Note that you don't need to escape the >
because it's no longer part of a regular command, and that you cannot put spaces between the parentheses ( ( something ) )
does something completely different from (( something ))
.
(( ))
lets you run a calculation/comparison/etc as though it were a command. It's also common to want to use the result of a calculation as part of a command; for that, use $(( ))
:
max_value=$(($(getconf ARG_MAX) - $(env|wc -c) - $(env|wc -l) * 4 - 2048))
test_value=$(ls -A | wc -l)
Note that I used $( )
instead of backticks; it does essentially the same thing, with somewhat cleaner syntax. And again, the arrangement of parentheses matter: $(( ))
does a calculation and captures its result; $( )
runs a command and captures its output. And $( ( ) )
would run a command in a pointless sub-subshell and capture its output. Oh, and I used ls -A
because find . -maxdepth 1
will include .
(the current directory) in its output, giving an overcount of 1. (And both the find
and ls
versions will miscount files with linefeeds in their name; oh, well.)
Then, to do the final comparison:
if ((test_value < max_value)) ; then echo "do this" else echo "do that" ; fi
Upvotes: 1