我的一个文件夹中有几个文件。我还有一个 csv 文件,其中包含按特定顺序列出的文件名(不带扩展名)。我想重命名文件夹中的文件,以在文件名开头包含文本文件列表中的位置。
换句话说,我的文件夹包含:
aaa.txt, bbb.txt, ccc.txt
文件名.csv 包含:
ccc
aaa
bbb
我想要获得的是:
1_ccc.txt, 2_aaa.txt 3_bbb.txt
我可以在 bash 中执行此操作吗?
答案1
for i in *.txt
do line=$(grep -nx -m 1 -- "${i%%.*}" filename.csv | cut -f 1 -d ':')
name=${line}_${i}
mv -- "$i" "$name"
done
解释
"${i%%.*}"
:按照 Kusalananda 的建议,取 的值,从值的尾部$i
剥离模式(更多信息.*
参数扩展)
grep -nF --
-x
匹配整行-m 1
在 1 个匹配行后停止读取文件(以避免grep
在文件很长时读取所有行)--
用于表示选项的结束(更多-- 在外壳中)-n
按以下格式返回行号而不是行本身2:aaa 3:bbb 1:ccc
cut -f 1 -d ':'
:
从上面的结果中提取带有 delimeter 的字段 1
答案2
awk 也可以是一个选项,这个也可以处理名称中的空格。
file='filename.csv'
find_path='/home/kali/test/'
extension='.txt'
awk -v find_path=$find_path -v extension=$extension \
'/^$/{NR=--NR; next} \
/^.+/ {print "mv -f " "\"" find_path $0 extension "\" " \
"\"" find_path NR "_" $0 extension "\"" \
}' $file | sh
答案3
假设您要重命名文件名前缀恰好是 CSV 文件中的字符串的所有文件,并且文件名具有.txt
文件名后缀(没有其他内容)。
#!/bin/sh
suffix=txt
n=0
while IFS= read -r prefix; do
n=$(( n + 1 ))
name=$prefix.$suffix
[ ! -e "$name" ] && [ ! -L "$name" ] && continue
mv -- "$name" "${n}_$name"
done <filename.csv
prefix
这会在循环的每次迭代中将CSV 中的一行读取到变量中,并将名称为(静态字符串)while
的文件重命名为,其中是一个变量,其值是已读取行数的简单计数器。$prefix.$suffix
$suffix
txt
${n}_$prefix.$suffix
n
mv
仅当源文件存在时才执行该命令。
没有对名称冲突进行测试。