2

我正在启动 bash 脚本,但我无法处理带间隔的文件名。我在这里搜索了有关我的问题的其他问题,例如:

如何在单行中输出用引号括起来的文件名?

在我的脚本中,我需要获取所有目录,为每个目录结束做一些工作。所以我的脚本的骨架是:

for directory in `find "$DIR" -type d`
do
# ... some work ...
done

此脚本不适用于带间隔的文件名。所以我尝试将 find 与 exec 结合使用,这似乎是一个优雅而简单的解决方案,但没有任何改变。更准确地说,我尝试过:

(I)  find "$DIR" -type d -exec echo -n '"{}" ' \;
(II) find "$DIR" -type d -exec echo -n '"{}" ' +

在使用命令 -exec 之前,我阅读了一些关于它的内容,但我仍然不清楚,所以:

  1. '"{}" ' \; 是什么以及如何工作
  2. 是什么以及如何工作 '"{}" ' +
  3. 我怎样才能为间隔文件名修复我的脚本?
4

3 回答 3

2

'"{}" ' \; 是什么以及如何工作

对于每个文件名,这将基本上执行 echo -n "\"filename\" ",产生一堆像"filename".

添加文字引号并没有帮助,因为 bash 不会开始将数据解释为 shell 脚本代码。

如果是read foo; ls $foo,则不能只输入$(rm /)运行命令,也不能只输入"foo bar"以避免拆分文件名。数据是数据,而不是代码,并且不尊重 shell 语法。

是什么以及如何工作 '"{}" ' +

+对文件名组运行一次​​命令(为了提高效率,而不是一次一个)。由于替换的工作方式,它与 相同{} +,因为参数只是被删除并替换为一堆文件名。

我怎样才能为间隔文件名修复我的脚本?

IFS您可以通过使用变量简单地更改 bash 用于拆分的字符,使其在 95% 的情况下工作:

IFS=$'\n'
for dir in $(find "$DIR" -type d)
do 
   echo "Directory: >> $dir <<"
done

这使得 bash 仅在换行符上拆分,而不是所有空格的默认值(这可能会在您的其余代码中产生一些有趣的副作用,因此您可能希望之后将 IFS 的值设置回其原始值)。

文件名也可以包含换行符。最好的方法是使用:

while IFS= read -d '' -r dir
do
    echo "Directory: >> $dir <<"
done < <(find "$DIR" -type d -print0)

这使得find输出文件被 NUL 字节分割,文件名永远不能包含这些字节。

于 2013-04-02T00:42:31.360 回答
1

这可能对您更有效:

while IFS= read -r adir ; do
    echo "Directory: $adir"
done < <(find "$DIR" -type d)
于 2013-04-01T22:36:49.013 回答
1

我使用这种格式并且效果很好:

find '/path/to/directories' -type d |\
  while read DIRNAME
  do
    echo "${DIRNAME}"
  done
于 2013-04-01T22:45:14.663 回答