我正在终端中使用 bash 尝试重命名文件夹:
1
2
3
4
5
我想根据.txt文件重命名它们:
a 2
c 3
d 5
e 1
b 4
.txt 文件中的顺序完全是随机的。我希望找到一种方法来重命名文件夹,使它们变成:
1 > e
2 > a
3 > c
4 > b
5 > d
有什么办法可以做到这一点?
多谢!
答案1
您可以xargs
使用mv
:
xargs -r -a /path/to/file.txt -L1 mv
(假设您位于文件所在的目录中)。
xargs
将输入转换为命令的参数。
-a foo
读取输入foo
。-L1
每次命令调用时只使用一行输入。-r
避免在行为空时运行命令
例如,使用echo mv
而不是mv
显示正在运行的命令:
$ xargs -r -a foo.txt -L1 echo mv
mv a 2
mv c 3
mv d 5
mv e 1
mv b 4
您还可以使用该选项在运行命令之前-p
进行确认:xargs
$ xargs -r -p -a foo.txt -L1 mv
mv a 2 ?...n
mv c 3 ?...n
mv d 5 ?...y
mv e 1 ?...mv: cannot stat ‘d’: No such file or directory
n
mv b 4 ?...
答案2
假设列表中的名称不包含空格, 以外之间名称,下面的脚本将从文本文件重命名文件夹递归地它将读取文件的行,将它们拆分为两个(新名称,旧名称),重命名出现的文件夹,这些文件夹由第二字符串在行中,进入第一的行中的字符串。
如上所述,它将执行此操作递归地,在目录树中从下到上。这可以防止脚本出现问题,尝试重命名可能已重命名父文件夹中的文件夹。
#!/usr/bin/env python
import os
import shutil
# -- set the (absolute) path to the targeted folder below
dr = "/home/jacob/Bureaublad/testfolder"
# -- set the path to the textfiles below
ren = "/home/jacob/Bureaublad/testfolder/renfile.txt"
renlist = [cpl for cpl in [l.split() for l in open(ren).readlines()] if cpl]
currnames = [r[1] for r in renlist]
for root, dirs, files in os.walk(dr, topdown = False):
for dr in dirs:
try:
# look up the name, pass if not in the list
i = currnames.index(dr)
except ValueError:
pass
else:
newname = renlist[i][0]
shutil.move(root+"/"+dr, root+"/"+newname)
如何使用
- 将脚本复制到一个空文件中(在纯文本编辑器),另存为
rename.py
- 在脚本的头部,设置文本文件和目录的实际路径
通过以下命令运行它(在终端中):
python /path/to/rename.py
解释
剧本:
- 创建一份名单夫妇:新名称/旧名称
- 使用 python 的
os.walk()
,它会从下到上递归地查看您的目录。 - 如果文件夹的名称与名称对中的第二项匹配,它会将文件夹重命名为第一个名称。
- 如果未列出该文件夹的名称,则它将保持不变。
答案3
文件中每行有一个条目a.txt
,因此列出的名称不包含\n
(换行)字符,对吗?
一行包含 2 个名字,用空间char,因此名称不包含空间char,对吧?(或者另一种可能性是对列出的名称使用固定长度)。
如果名称不包含字符,请尝试以下\n
操作space
:
awk '{printf("%s\0%s\0",$2,$1)}' a.txt | xargs -0 -L 2 mv
awk
用于反转从a.txt
文件读取的行中名称的顺序。\0
用于在将名称打印到标准输出时分隔名称。
xargs
读取标准输入:
-0
:\0
用作从标准输入读取的元素的分隔符-L 2 mv
:mv
命令每次调用时都带有 2 个参数。
考试:
$ ls -al
total 40
drwxrwxr-x 7 stacko stacko 4096 May 31 11:25 .
drwxrwxr-x 21 stacko stacko 12288 May 31 11:23 ..
drwxrwxr-x 2 stacko stacko 4096 May 31 11:25 1
drwxrwxr-x 2 stacko stacko 4096 May 31 11:25 2
drwxrwxr-x 2 stacko stacko 4096 May 31 11:25 3
drwxrwxr-x 2 stacko stacko 4096 May 31 11:25 4
drwxrwxr-x 2 stacko stacko 4096 May 31 11:25 5
-rw-rw-r-- 1 stacko stacko 20 May 31 11:24 a.txt
$ cat a.txt
a 2
c 3
d 5
e 1
b 4
$ awk '{printf("%s\0%s\0",$2,$1)}' a.txt | xargs -0 -L 2 mv -v
'2' -> 'a'
'3' -> 'c'
'5' -> 'd'
'1' -> 'e'
'4' -> 'b'
$ ls -al
total 40
drwxrwxr-x 7 stacko stacko 4096 May 31 11:26 .
drwxrwxr-x 21 stacko stacko 12288 May 31 11:23 ..
drwxrwxr-x 2 stacko stacko 4096 May 31 11:25 a
-rw-rw-r-- 1 stacko stacko 20 May 31 11:24 a.txt
drwxrwxr-x 2 stacko stacko 4096 May 31 11:25 b
drwxrwxr-x 2 stacko stacko 4096 May 31 11:25 c
drwxrwxr-x 2 stacko stacko 4096 May 31 11:25 d
drwxrwxr-x 2 stacko stacko 4096 May 31 11:25 e
答案4
在上面显示的简单情况下,每行有两个“单词”,即目标目录和新名称,并且都不包含任何空格,您可以简单地执行以下操作:
while read -r from to; do mv "$from" "$to"; done < file
这将读取每一行,将file
第一个字符串(直到第一个空格)分配给并将$from
该行的其余部分分配给$to
,然后mv
在每一行上运行。