Bash - Strings, Commands and Escaping (oh, my!)

2020-02-16 01:08发布

I'm wasting so much time right now trying to figure out something so simple....

pseudo code (mixture of several syntax's, sorry):

cmd1 = "find /my/starting/path -type f | grep -v -f /my/exclude/files"
cmd2 = " nl -ba -s'  ' "
cmd3 = " | xargs mv -t /move/here/dir " 

echo run_command_and_return_output($cmd1$cmd2)

$cmd1$cmd3  # just this now... 

# i don't actually want a function... but the name explains what i want to do
function run_command_and_return_output(){ /* magic */ }

this works....

FIND=$(find $LOG_DIR -type f | grep -v -f $EXCLUDE | nl -ba -s'   ')

printf "%s\n" "$FIND"

this does not...

NL="nl -ba -s'  '"
FIND=$(find $LOG_DIR -type f -mtime +$ARCH_AGE | grep -v -f $EXCLUDE | $NL)

printf "%s\n" "$FIND"

and neither does this...

NL='nl -ba -s'\''   '\'' '

this definitely does work, though:

find /my/starting/path -type f | grep -v -f /my/exclude/files |  nl -ba -s'  ' 

or

FIND=$(find $LOG_DIR -type f -mtime +$ARCH_AGE | grep -v -f $EXCLUDE | nl -ba -s'  ' )

标签: bash shell
1条回答
何必那么认真
2楼-- · 2020-02-16 01:54

Short form: Expanding $foo unquoted runs the content through string-splitting and glob expansion, but not syntactical parsing. This means that characters which would do quoting and escaping in a different context aren't honored as syntax, but are only treated as data.

If you want to run a string through syntactical parsing, use eval -- but mind the caveats, which are large and security-impacting.

Much better is to use the right tools for the job -- building individual simple commands (not pipelines!) in shell arrays, and using functions as the composable unit for constructing complex commands. BashFAQ #50 describes these tools -- and goes into in-depth discussion on which of them is appropriate when.


To get a bit more concrete:

nl=( nl -ba -s'  ' )
find_output=$(find "$log_dir" -type f -mtime "+$arch_age" | grep -v -f "$exclude" | "${nl[@]}")
printf "%s\n" "$find_output"

...would be correct, since it tracks the simple command nl as an array.

查看更多
登录 后发表回答