我有几个包含文件的目录,这些文件的名称包含文件夹的名称。 例如:
one/berg - one.txt
two/tree - two.txt
three/water - three.txt
我希望如此:
one/berg.txt
two/tree.txt
three/water.txt
我尝试使用sed命令,find命令,命令等。 我失败了必须找到一种方法来获得它。
你可以帮助我吗?谢谢答案 0 :(得分:1)
简短,如果你有GNU find:
find . -name '* - *.*' -execdir bash -c '
for file; do
ext=${file##*.}
mv -- "$file" "${file%% - *}.${ext}"
done
' _ {} +
-execdir
在找到每组文件的目录中执行给定的命令,因此不必担心目录名称。for file; do
是写for file in "$@"; do
的简短方法。${file##*.}
扩展为$file
的内容,其中包含最后一个.
已移除的内容(因此,它会扩展到文件的扩展名)。"${varname%% - *}"
扩展为变量varname
的内容,并在<space><dash><space>
之后删除所有内容。-exec bash -c '...' _ {} +
中(与-execdir
一样),传递给bash -c
的脚本以_
作为$0
运行,所有文件由find
在随后的职位中。答案 1 :(得分:0)
在sed的帮助下,这是一种方法:
#!/bin/bash
find -type f -print0 | \
while IFS= read -r -d '' old_path; do
new_path="$(echo "$old_path" | sed -e 's|/\([^/]\+\)/\([^/]\+\) - \1.\([^/.]\+\)$|/\1/\2.\3|')"
if [[ $new_path != $old_path ]]; then
echo mv -- "$old_path" "$new_path"
# ^^^^ remove this "echo" to actually rename the files
fi
done
您必须cd
到包含所有这些文件的顶级目录才能执行此操作。此外,它会保留echo
,因此它实际上不会重命名文件。运行一个以查看您是否喜欢其输出,如果您喜欢,请删除echo
并再次运行。
基本思想是我们迭代所有文件,对于每个文件,我们尝试查找文件是否与给定模式匹配。如果是,我们重命名它。该模式检测(并捕获)路径的倒数第二个组件,并将路径的最后一个组件分为3个部分:前缀,后缀(必须与前一个路径组件匹配)和扩展。