正确引用 bash 别名定义
Properly quote bash alias definition
我试图将以下命令放入 bash 别名中。该命令本身运行良好,但当我尝试为其设置别名时,出现以下错误:
命令
find . -maxdepth 1 -mindepth 1 -type d -exec sh -c 'echo "$(find "{}" -type f | wc -l)" {}' \; | sort -nr
别名
alias csfiles='find . -maxdepth 1 -mindepth 1 -type d -exec sh -c 'echo "$(find "{}" -type f | wc -l)" {}' \; | sort -nr'
错误:
-sh: alias 0: not found
-sh: alias {} \; | sort nr: not found
我认为这意味着我没有正确使用引号,但我无法确定正确的组合。帮忙?
您可以在定义周围使用双引号,如下所示:
alias foo="find . -maxdepth 1 -mindepth 1 -type d -exec sh -c 'echo \"$(find \"{}\" -type f | wc -l)\" {}' \; | sort -nr"
定义中的每个文字 "
都被转义:\"
.
注意:您还需要转义内部命令替换,以防止它在别名定义时扩展。像这样... $(...)
作为对 chepners 评论的后续,您应该将文件名作为参数传递给内部查找命令。否则,如果您的其中一个文件夹的名称中包含 "
,您将 运行 遇到问题:
alias foo="find . -maxdepth 1 -mindepth 1 -type d -exec bash -c 'echo \"$(find \"${1}\" -type f | wc -l) \"${1}\" \"' -- \"{}\" \; | sort -nr"
你的外部 find
不会做任何你不能用简单的 glob 做的事情。这消除了一层引号(连同找到的每个目录的 sh
过程)。
# Ignoring the issue of assuming no file name contains a newline
for d in ./*/; do
echo "$(find "$d" -type f | wc -l) $d"
done
只需定义一个shell函数来消除强加给alias
的参数的第二层。
csfiles () {
for d in ./*/; do
echo "$(find "$d" -type f | wc -l) $d"
done
}
其余对 find
的调用也可以替换为 for
循环,消除每个文件名一行的有问题的假设:
csfiles () {
for d in ./*/; do
echo "$(for f in "$d"/*; do [ -f "$f" ] && echo; done | wc -l) $d"
done
}
你可以保留 find
如果它支持 -printf
主,因为你不关心文件的实际名称,只关心每个文件只有一行输出。
csfiles () {
for d in ./*/; do
echo "$(find "$d" -type f -printf . | wc -l) $d"
done
}
我试图将以下命令放入 bash 别名中。该命令本身运行良好,但当我尝试为其设置别名时,出现以下错误:
命令
find . -maxdepth 1 -mindepth 1 -type d -exec sh -c 'echo "$(find "{}" -type f | wc -l)" {}' \; | sort -nr
别名
alias csfiles='find . -maxdepth 1 -mindepth 1 -type d -exec sh -c 'echo "$(find "{}" -type f | wc -l)" {}' \; | sort -nr'
错误:
-sh: alias 0: not found
-sh: alias {} \; | sort nr: not found
我认为这意味着我没有正确使用引号,但我无法确定正确的组合。帮忙?
您可以在定义周围使用双引号,如下所示:
alias foo="find . -maxdepth 1 -mindepth 1 -type d -exec sh -c 'echo \"$(find \"{}\" -type f | wc -l)\" {}' \; | sort -nr"
定义中的每个文字 "
都被转义:\"
.
注意:您还需要转义内部命令替换,以防止它在别名定义时扩展。像这样... $(...)
作为对 chepners 评论的后续,您应该将文件名作为参数传递给内部查找命令。否则,如果您的其中一个文件夹的名称中包含 "
,您将 运行 遇到问题:
alias foo="find . -maxdepth 1 -mindepth 1 -type d -exec bash -c 'echo \"$(find \"${1}\" -type f | wc -l) \"${1}\" \"' -- \"{}\" \; | sort -nr"
你的外部 find
不会做任何你不能用简单的 glob 做的事情。这消除了一层引号(连同找到的每个目录的 sh
过程)。
# Ignoring the issue of assuming no file name contains a newline
for d in ./*/; do
echo "$(find "$d" -type f | wc -l) $d"
done
只需定义一个shell函数来消除强加给alias
的参数的第二层。
csfiles () {
for d in ./*/; do
echo "$(find "$d" -type f | wc -l) $d"
done
}
其余对 find
的调用也可以替换为 for
循环,消除每个文件名一行的有问题的假设:
csfiles () {
for d in ./*/; do
echo "$(for f in "$d"/*; do [ -f "$f" ] && echo; done | wc -l) $d"
done
}
你可以保留 find
如果它支持 -printf
主,因为你不关心文件的实际名称,只关心每个文件只有一行输出。
csfiles () {
for d in ./*/; do
echo "$(find "$d" -type f -printf . | wc -l) $d"
done
}