【问题标题】:Linux rename files as dirnameLinux 将文件重命名为 dirname
【发布时间】:2016-08-01 01:03:30
【问题描述】:
我有很多这样的文件:
./1/wwuhw.mp3
./2/nweiewe.mp3
./3/iwqjoiw.mp3
./4/ncionw.MP3
./5/joiwqfm.wmv
./6/jqoifiew.WMV
如何在 Linux Bash 中像这样重命名它们:
./1/1.mp3
./2/2.mp3
./3/3.mp3
./4/4.MP3
./5/5.wmv
./6/6.WMV
【问题讨论】:
标签:
linux
bash
find
rename
【解决方案1】:
for 循环方法,如其他一些答案中所述,对于大多数需要将目录中的 每个 文件重命名为第一个父目录名称的情况来说就足够了并且效果很好.我的特殊情况需要更多粒度,我只想重命名目录中文件的 子集 并断言操作数实际上是一个实际的 文件,而不是空目录、符号链接等。使用find 可以完全实现您想要的,此外还可以对文件输入和输出应用过滤和处理。
#####################################
# Same effect as using a `for` loop #
#####################################
#
# -mindepth 2 : ensures that the file has a parent directory.
# -type f : ensures that we are working with a `regular file` (not directory, symlink, etc.).
find . -mindepth 2 -type f -exec bash -c 'file="{}"; dir="$(dirname $file)"; mv "$file" "$dir/${dir##*/}.${file##*.}"' \;
#########################
# Additional filtration #
#########################
# mp3 ONLY (case insensitive)
find . -mindepth 2 -type f -iname "*.mp3" -exec bash -c 'file="{}"; dir="$(dirname $file)"; mv "$file" "$dir/${dir##*/}.${file##*.}"' \;
# mp3 OR mp4 ONLY (case insensitive)
find . -mindepth 2 -type f \( -iname "*.mp3" -or -iname "*.mp4" \) -exec bash -c 'file="{}"; "dir=$(dirname $file)"; mv "$file" "$dir/${dir##*/}.${file##*.}"' \;
【解决方案2】:
如果你不介意使用外部工具,那么rnm 可以很容易地做到这一点:
rnm -ns '/pd0/./e/' */*
/pd0/ 是直接父目录,/pd1/ 是之前的目录,依此类推。
-ns 表示 名称字符串 和 /pd/ 和 /e/ 是 名称字符串规则 扩展为 父目录 和 文件扩展名。
/pd/规则的一般格式为/pd<digit>-<digit>-<delim>/,例如/pd0-2-_/之类的规则将从dir2/dir1/dir0的目录结构构造dir0_dir1_dir2
更多示例请见here。
【解决方案3】:
试试这个,
for i in */*; do mv $i $(dirname $i)/$(dirname $i).${i##*.}; done
For 循环逐个遍历目录中的每个文件。 mv 语句将目录中的每个文件一一重命名。
【解决方案4】:
这样的事情应该可以完成:
for i in */*; do
echo mv "${i}" "${i%/*}/${i%/*}.${i##*.}"
done
参见例如here,这个神秘的参数扩展(如${i%/*})在bash 中意味着什么。
上面的脚本只会打印控制台中的命令,不会调用它们。一旦确定要继续,您可以删除 echo 语句并让它运行。