我有一个这样的目录结构:
Bookname Edition 1
Bookname Edition 1 type1.pdf
Bookname Edition 1 type2.pdf
Bookname Edition 2
Bookname Edition 2 type1.pdf
Bookname Edition 2 type2.pdf
我想递归地将目录的名称从更改Edition
为Volume
和这些目录中的文件名。
我从这个开始,如果我在目录中,那就没问题:
for f in *.pdf; do
a="$(echo $f | sed s/Edition/Volume/)"
mv "$f" "$a"
done
然后我尝试通过这个来改变目录下的所有文件,但是这时我遇到了困难......
请告诉我如何操作或提供更好的方法。100 个目录中有 15000 个 PDF。
答案1
如果您的结构只有两个级别,则不需要使用递归。
不要使用 来解析文件名sed
。如果你想使用正则表达式和sed
样式语法来重命名文件,请使用rename
。如果你使用的是 Ubuntu 17.10,则需要安装它
sudo apt install rename
然后你可以使用pa4080 的回答。
使用rename
,使用-n
选项进行测试。
rename -n 'expression' file(s)
您也可以直接使用mv
命令。作为一行命令:
for d in ./*/; do mv -v "$d" "${d/Edition/Volume}"; done; for f in ./*/*; do mv -v "$f" "${f/Edition/Volume}"; done
您可以使用echo
进行测试mv
,即echo mv -v source dest
,但它会在这里给出不准确的结果,除非您测试然后单独运行循环。
作为脚本:
#!/bin/bash
# rename directories first
for d in ./*/; do
mv -v "$d" "${d/Edition/Volume}"
done
# now rename files
for f in ./*/*; do
mv -v "$f" "${f/Edition/Volume}"
done
mv
和rename
识别--
表示选项的结束。由于./
本例中所有路径都以 开头,我们不需要使用它,但如果路径可以以 开头,则在选项末尾-
使用,例如,以防止这些路径被解释为选项。--
rename -n -- 's/foo/bar/' *
答案2
rename
你可以使用两次该命令来完成此任务:
rename 's/Edition/Volume/' */ # rename the directories
rename 's/Edition/Volume/' */*.pdf # rename the PDF files inside
以下是两个类似的问题:
答案3
在多级目录中,您可以一步完成此操作,但问题是您需要确保从下到上重命名目录,以防止命令或脚本在更改目录内容之前更改目录名称。
在python中,你可以使用:
os.walk
结合
topdown=False
在脚本中:
#!/usr/bin/env python3
import os
import shutil
import sys
for root, dirs, files in os.walk(sys.argv[1], topdown=False):
for f in files:
shutil.move(
root+"/"+f, root+"/"+f.replace("Edition", "Volume").strip()
)
for dr in dirs:
shutil.move(
root+"/"+dr, root+"/"+dr.replace("Edition", "Volume").strip()
)
将脚本另存为change_name.py
,并使用目录作为参数运行它:
python3 /path/to/change_name.py <directory>
这可以在任意数量的级别上递归地进行。
答案4
find
与-depth
选项结合使用prename
:
find [DIRS...] -depth | prename -n 's|Edition(?=[^/]*$)|Volume|'
解释:
-depth
先选择目录子目录,再选择其父目录。然后,使用所选路径名进行重命名的工具可以先重命名子目录,再重命名其父目录。s|Edition(?=[^/]*$)|Volume|
Edition
将路径名中第一次出现的替换为Volume
但只有如果余数不包含/
,即,它仅适用于最后一个路径名组件(通过正向前瞻实现(?=[^/]*$)
)。-n
告诉prename
不要真正重命名路径,而是打印如何重命名它们。删除此选项即可真正重命名它们。