问题
I have the following command that I am trying to put into a bash alias. The command by itself works fine, but when I try to alias it, I am getting the following errors:
The Command
find . -maxdepth 1 -mindepth 1 -type d -exec sh -c 'echo "$(find "{}" -type f | wc -l)" {}' \; | sort -nr
The Alias
alias csfiles='find . -maxdepth 1 -mindepth 1 -type d -exec sh -c 'echo "$(find "{}" -type f | wc -l)" {}' \; | sort -nr'
The Error:
-sh: alias 0: not found
-sh: alias {} \; | sort nr: not found
I think this means I am not using quotes right but I am having trouble determining the correct combo. Help?
回答1:
Your outer find
doesn't do anything you couldn't do with a simple glob. This eliminates a layer of quotes (along with the sh
process for each directory found).
# Ignoring the issue of assuming no file name contains a newline
for d in ./*/; do
echo "$(find "$d" -type f | wc -l) $d"
done
Just define a shell function to eliminate the second layer imposed on the argument to alias
.
csfiles () {
for d in ./*/; do
echo "$(find "$d" -type f | wc -l) $d"
done
}
The remaining call(s) to find
can also be replaced with a for
loop, eliminating the problematic assumption of one line per file name:
csfiles () {
for d in ./*/; do
echo "$(for f in "$d"/*; do [ -f "$f" ] && echo; done | wc -l) $d"
done
}
You could keep find
if it supports the -printf
primary, because you don't care about the actual names of the files, just that you get exactly one line of output per file.
csfiles () {
for d in ./*/; do
echo "$(find "$d" -type f -printf . | wc -l) $d"
done
}
回答2:
You can use double quotes around the definition, like this:
alias foo="find . -maxdepth 1 -mindepth 1 -type d -exec sh -c 'echo \"\$(find \"{}\" -type f | wc -l)\" {}' \; | sort -nr"
Every literal "
inside the definition gets escaped: \"
.
Note: You also need to escape the inner command substitution to prevent it from getting expanded upon alias definition time. Like this ... \$(...)
As a follow up on chepners comment, you should pass the filename to the inner find command as an argument. Otherwise you will run into problems if one of your folders has a name with a "
in it:
alias foo="find . -maxdepth 1 -mindepth 1 -type d -exec bash -c 'echo \"\$(find \"\${1}\" -type f | wc -l) \"\${1}\" \"' -- \"{}\" \; | sort -nr"
来源:https://stackoverflow.com/questions/53398792/properly-quote-bash-alias-definition