Shell 脚本失败,目录名中有空格

Shell 脚本失败,目录名中有空格,shell,Shell,我有一个非常简单的问题,我已经找到了一堆类似的问题的答案,但没有一个能为我解决这个问题 我有一个shell脚本,它遍历一个目录并打印出子目录中的文件和目录数,后跟目录名 然而,对于带有空格的目录,它失败了,它尝试将每个单词用作新参数。我试着在报价单中加入$dir,但没有帮助。也许是因为它已经出现在回音语录里了 for dir in `find . -mindepth 1 -maxdepth 1 -type d` do echo -e "`ls -1 $dir | wc -l`\t$dir

我有一个非常简单的问题,我已经找到了一堆类似的问题的答案,但没有一个能为我解决这个问题

我有一个shell脚本,它遍历一个目录并打印出子目录中的文件和目录数,后跟目录名

然而,对于带有空格的目录,它失败了,它尝试将每个单词用作新参数。我试着在报价单中加入$dir,但没有帮助。也许是因为它已经出现在回音语录里了

for dir in `find . -mindepth 1 -maxdepth 1 -type d`
do
    echo -e "`ls -1 $dir | wc -l`\t$dir"
done
提前感谢您的帮助:)

警告:下面三个代码示例中有两个使用Bashism。如果需要POSIX sh而不是bash,请注意使用正确的


不要做这些事。如果您真正的问题涉及使用find,您可以这样使用它:

shopt -s nullglob
while IFS='' read -r -d '' dir; do
  files=( "$dir"/* )
  printf '%s\t%s\n' "${#files[@]}" "$dir"
done < <(find . -mindepth 1 -maxdepth 1 -type d -print0)
如果您试图以与POSIX sh兼容的方式执行此操作,可以尝试以下操作:

for dir in */; do
  [ "$dir" = "*/" ] && continue
  set -- "$dir"/*
  [ "$#" -eq 1 ] && [ "$1" = "$dir/*" ] && continue
  printf '%s\t%s\n' "$#" "$dir"
done
您不应该在脚本中使用
ls

您不应该使用
for
来读取行:

在清点文件时使用数组和glob安全、可靠地执行此操作,无需外部命令:

总是NUL terminate文件列表出自
find
——否则,包含换行符的文件名(是的,它们在UNIX中是合法的!)会导致单个名称被读取为多个文件,或者(在某些find版本和用法中)您的“文件名”与实际文件名不匹配

警告:下面三个代码示例中有两个使用bashism。如果需要POSIX sh而不是bash,请注意使用正确的


不要做这些事。如果您真正的问题涉及使用find,您可以这样使用它:

shopt -s nullglob
while IFS='' read -r -d '' dir; do
  files=( "$dir"/* )
  printf '%s\t%s\n' "${#files[@]}" "$dir"
done < <(find . -mindepth 1 -maxdepth 1 -type d -print0)
如果您试图以与POSIX sh兼容的方式执行此操作,可以尝试以下操作:

for dir in */; do
  [ "$dir" = "*/" ] && continue
  set -- "$dir"/*
  [ "$#" -eq 1 ] && [ "$1" = "$dir/*" ] && continue
  printf '%s\t%s\n' "$#" "$dir"
done
您不应该在脚本中使用
ls

您不应该使用
for
来读取行:

在清点文件时使用数组和glob安全、可靠地执行此操作,无需外部命令:


总是NUL terminate文件列表出自
find
——否则,包含换行符的文件名(是的,它们在UNIX中是合法的!)会导致单个名称被读取为多个文件,或者(在某些find版本和用法中)您的“文件名”与实际文件名不匹配

无论
find发生了什么-明德普…|读dir时;做完成
sigh@robertklep这个版本不太正确;它错误地处理了一些带有反斜杠的名称、以IFS字符结尾的名称以及任何包含换行符的名称。此外,while循环退出时,对变量所做的任何更改都将被忽略,因为它位于管道的右侧。@CharlesDuffy和最初发布的版本(我对此作出响应)捕获了所有这些问题?;)@CharlesDuffy这取决于shell,
ksh
执行当前shell中管道的最后一个命令。@robertklep不,但这里的响应点是帮助人们以正确的方式做事。
find发生了什么-明德普…|读dir时;做完成
sigh@robertklep这个版本不太正确;它错误地处理了一些带有反斜杠的名称、以IFS字符结尾的名称以及任何包含换行符的名称。此外,while循环退出时,对变量所做的任何更改都将被忽略,因为它位于管道的右侧。@CharlesDuffy和最初发布的版本(我对此作出响应)捕获了所有这些问题?;)@CharlesDuffy这取决于shell,
ksh
执行当前shell中管道的最后一个命令。@robertklep没有,但这里的响应点是帮助人们以正确的方式做事。非常感谢:)正如你所说,我对这一点很陌生。你能给我解释几句吗?--如果s=''read-r-d''dir--files=(“$dir”/*)--done<@Chris如果它说nullglob无效,那么您的shell可能不是bash(这其中的其他部分也不起作用)。请参阅mywiki.wooledge.org/BashGuide的“选择您的shell”部分/Practices@Chris我添加了与POSIX兼容的答案版本;这个应该适合你。任何引用格雷格维基的答案都应该得到+1。非常感谢:)你可以告诉我,我对这个很陌生。你能给我解释几句吗?--如果s=''read-r-d''dir--files=(“$dir”/*)--done<@Chris如果它说nullglob无效,那么您的shell可能不是bash(这其中的其他部分也不起作用)。请参阅mywiki.wooledge.org/BashGuide的“选择您的shell”部分/Practices@Chris我添加了与POSIX兼容的答案版本;这个应该适合你。任何引用格雷格维基的答案都应该得到+1。