我试图将子目录中的所有文件合并为一个新文件,并将新合并的文件命名为与子目录相同的名称,但我不知道如何在 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
)来执行以下操作:
- 进入每个唯一的目录,并对该目录内的每个文件执行命令(在我的情况下,将它们全部复制到不同的目录)。
- 然后,我编写了一个不同的脚本
script.sh
来执行另一个命令(在本例中,将所有 PDF 合并为一个文件temp.pdf
)。然后,我想temp.pdf
根据目录重命名该文件Unique name.pdf
(带空格)。 - 我必须对多个子目录执行此过程。
我尝试过使用多个 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
- 创建
for
循环并find /home/ -type f -name "*.pdf"
作为变量 - 将文件复制到您需要的位置,获取 $VARIABLE 并通过 sed/awk 处理以删除“/”。
发布您的脚本,我们可以帮助您改进它。
您可以随时运行脚本来bash -x
调试它们,或者您可以设置!#/bin/bash -x
为始终在调试(详细)模式下执行。