BASE_DIR_APP_CONN="/opt/"
CMD_CONFIG_SNAPSHOT_DIR_APP_CONN="ls -ltrh $BASE_DIR_APP_CONN/local/ | awk '{print \$NF}' | tail -n 2 | xargs"
echo $CMD_CONFIG_SNAPSHOT_DIR_APP_CONN
for dir in $($CMD_CONFIG_SNAPSHOT_DIR_APP_CONN)
do
echo "$dir"
done
Why this throws below error:
ls: cannot access |: No such file or directory
ls: cannot access awk: No such file or directory
ls: cannot access '{print: No such file or directory
ls: cannot access $NF}': No such file or directory
ls: cannot access |: No such file or directory
ls: cannot access tail: No such file or directory
ls: cannot access 2: No such file or directory
ls: cannot access |: No such file or directory
ls: cannot access xargs: No such file or directory
/opt/local/:
.....
When I run for loop with a command directly, it works as expected. Can someone please help? Thank you !
CodePudding user response:
Spliting a string into individual commands (i.e. breaking the pieces by |
, ;
and so on), is done before parameter expansion. Therefore,
foo | bar
runs foo
and bar
, connected by a pipe. However,
nonsense="foo | bar"
$nonsense
invokes the command foo
with the two parameters |
and bar
. In order to run the pipe stored into the variable, I would have to write something like
eval "$nonsense"
but in general, this is a bad idea to do, not the least because you sooner or later will run into trouble with quoting and whitespace issues (as you would see if you tried this with your string).
In your case, I would use a function, for instance:
CMD_CONFIG_SNAPSHOT_DIR_APP_CONN() {
ls -ltrh $BASE_DIR_APP_CONN/local/ | awk '{print \$NF}' | tail -n 2 | xargs
}
and calling it as
for dir in $(CMD_CONFIG_SNAPSHOT_DIR_APP_CONN)
Of course, this still suffers from several problems, such as parsing the output of ls
and piping it into awk
(this will break if the directory entries contain whitespace character), but this is not topic of your question, so I leave it like this.