我有大约 100 个目录,例如:
- 步行,
- 写作,
- 跳舞,
- 游泳。
每个目录都包含一组文件。
我想将目录的前缀名称添加到其文件的文件名中。
例如:
writing :
0ZPQl5QUvo0_000202_000212.mp4
AFV8x8ezN8g_000016_000026.mp4
-HutuMqTAPw_000275_000285.mp4
qtvsw6h3yQo_000228_000238.mp4
Ub0rc6U6nfI_000100_000110.mp4
变成:
writing :
writing_0ZPQl5QUvo0_000202_000212.mp4
writing_AFV8x8ezN8g_000016_000026.mp4
writing_-HutuMqTAPw_000275_000285.mp4
writing_qtvsw6h3yQo_000228_000238.mp4
writing_Ub0rc6U6nfI_000100_000110.mp4
我怎样才能做到这一点?
答案1
这是脚本的一个稍微改进的版本 - 主要区别在于
使用 shell glob
*
代替$(ls)
- 参见Bash 陷阱 #1引用任何变量扩展(允许文件名带有空格或其他奇怪字符 - 参见Bash 陷阱 #2)
mv
标记使用GNU 扩展的选项的结束--
- 这使得它也能处理以连字符开头的文件名
所以
for d in *; do
[[ -d "$d" ]] && cd "$d" || continue
for f in *.mp4; do
echo mv -v -- "${f}" "${d}_${f}"
done
cd -
done
或者,更便携的是,你可以循环./*.mp4
以避免前导连字符 - 但随后你必须在mv
for d in *; do
[ -d "$d" ] && cd "$d" || continue
for f in ./*.mp4; do
echo mv -v "${f}" "${d}_${f#./}"
done
cd -
done
无论哪种情况,一旦您确定它按预期工作,请删除echo
(如果您愿意,还可以删除)。-v
答案2
使用以下脚本可以解决该问题:
for i in $(ls); do
if [ -d $i ]; then
fname=${i##*/}
echo $fname
cd $i
for z in *.mp4; do
echo $z
cp $z ${fname}_${z}
rm $z
done
cd ..
fi
done
答案3
假设你位于包含所有这些目录的目录中dancing
,writing
命令
for folder in $(find -mindepth 1 -type d); do
cd $folder
PRE=${folder#./}
for file in *; do
mv "$file" "${PRE}_$file"
done
cd ..
done
将实现您想要的效果。我测试过,即使文件名包含空格或换行符,它也能正常工作。但是,如果文件夹名称中包含此类字符,则不起作用,例如walking slowly
。
编辑:上述代码无法处理文件夹名称中的空格或换行符。要解决此问题,请使用修改后的代码
for folder in *; do
if [ -d "$folder" ]; then
cd "$folder"
PRE=${folder#./}
for file in *; do
mv "$file" "${PRE}_$file"
done
cd ..
fi
done
编辑2:如果文件名以-
(破折号)开头,命令可能会将其解释为选项。要处理前导破折号,请在命令及其参数--
之间插入一个。这告诉停止扫描选项。mv
mv
所以最终的代码是
for folder in *; do
if [ -d "$folder" ]; then
cd "$folder"
for file in *; do
mv -- "$file" "${folder}_$file"
done
cd ..
fi
done
答案4
使用find
和prename
:
find DIR... -mindepth 1 -type f | prename -n 's/([^\/]+)\/([^\/]+)$/$1\/$1_$2/'
删除-n
实际重命名文件的选项,而不仅仅是打印文件如何重命名。