如何递归遍历目录并以目录名命名文件?

如何递归遍历目录并以目录名命名文件?

我试图将子目录中的所有文件合并为一个新文件,并将新合并的文件命名为与子目录相同的名称,但我不知道如何在 Bash 中执行此操作。以下是我处理它的方法:我有许多目录,每个目录都有一个唯一的文件名(带空格!)。在每个目录中,都有许多以数字命名的文件,如下所示:

Home/Unique name/1.pdf  
Home/Unique name/2.pdf  
Home/Unique name/3.pdf  
Home/Unique name/4.pdf  
....  
Home/Other Unique name/1.pdf  
Home/Other Unique name/2.pdf  
Home/Other Unique name/3.pdf  
Home/Other Unique name/4.pdf

我想要做的是编写一个 bash 脚本(从目录Home)来执行以下操作:

  1. 进入每个唯一的目录,并对该目录内的每个文件执行命令(在我的情况下,将它们全部复制到不同的目录)。
  2. 然后,我编写了一个不同的脚本script.sh来执行另一个命令(在本例中,将所有 PDF 合并为一个文件temp.pdf)。然后,我想temp.pdf根据目录重命名该文件Unique name.pdf(带空格)。
  3. 我必须对多个子目录执行此过程。

我尝试过使用多个 for 循环、while 循环和 find 命令来解决问题,但我对 bash 不够熟悉,无法轻松地进行调试或自信地使用这些变量。我也确信有更有效的方法来完成我正在做的事情,但我花了一段时间才将脚本整合在一起。

答案1

POSIX 方式是使用print . -type d ... | while read f; do,但除非你执着于 100% 的可移植性,否则我不会为此烦恼。如果你有 bash 4+ 和pdfunite(默认情况下安装在我的 Ubuntu 13.04 上),你可以用两行代码执行此操作:

shopt -s globstar
for f in ./**/; do pdfunite "$f"/*.pdf "$f"/"$(basename "$f").pdf"; done

请注意,shopt -s globstar需要与其余部分单独成行。启用 globstar 后,**将递归扩展到当前目录中的所有文件和目录。由于文件/名称中不能包含,**/因此将仅扩展到目录。我使用./**/这个选项来防止您的目录以连字符 ( -) 开头(这种情况不太可能发生),因为这可能会导致问题,因为许多程序将以 开头的任何内容视为-选项。

如上所述,这不会将 PDF 复制到另一个目录,但添加起来非常简单:

for f in ./**/; do cp "$f"/*.pdf /target/dir/; pdfunite "$f"/*.pdf "$f"/"$(basename "$f").pdf"; done

如果您想使用自己自定义的 pdf 合并脚本,那么只需更改适合的行即可 - 但请记住,shell 脚本的本质是组合预先存在的命令。

这是一个更便携的版本:

print . -type d -print0 | while read -d $'\0' f; do
  pdfunite "$f"/*.pdf "$f"/"$(basename "$f").pdf"
done

答案2

  1. 创建for循环并find /home/ -type f -name "*.pdf"作为变量
  2. 将文件复制到您需要的位置,获取 $VARIABLE 并通过 sed/awk 处理以删除“/”。

发布您的脚本,我们可以帮助您改进它。

您可以随时运行脚本来bash -x调试它们,或者您可以设置!#/bin/bash -x为始终在调试(详细)模式下执行。

相关内容