在 macOS 上使用 Bash 递归重命名文件和目录
Recursively Rename Files and Directories with Bash on macOS
我正在编写一个将执行某些操作的脚本,其中一个操作是在文件名和目录名中查找所有出现的字符串,并将其替换为另一个字符串。
目前我有这个
find . -name "*foo*" -type f -depth | while read file; do
newpath=${file//foo/bar}
mv "$file" "$newpath"
done
只要文件路径不包含 foo
,这就可以正常工作,但不能保证。
我觉得解决这个问题的方法是先更改文件名,然后返回并更改目录名,但即便如此,如果您的结构包含多个目录 foo
在里面,将无法正常工作。
有没有办法使用内置的 macOS 工具来做到这一点? (我说内置,因为这个脚本将分发给我们组织中的其他一些人,它不能依赖任何要安装的包)。
将 path_name 与 file_name 分开,类似于
#!/usr/bin/env bash
while read -r file; do
path_name="${file%/*}"; printf 'Path is %s\n' "$path_name"
file_name="${file#"$path_name"}"; printf 'Filename is %s\n' "$file_name"
newpath="$path_name${file_name//foo/bar}"
echo mv -v "$file" "$newpath"
done < <(find . -name "*foo*" -type f)
也看看 basename
和 dirname
。
printf
只是为了显示路径和文件名。
脚本只是将 file_name 中的 foo
替换为 bar
,用 path_name 也可以完成,只需使用相同的语法即可。
newpath="${path_name//bar/more}${file_name//foo/bar}"
因此重命名 path_name 和 file_name。
或者像您的想法一样重命名 path_name 然后 file_name 也是一种选择。
path_name="${file%/*}"
file_name="${file#"$path_name"}"
new_pathname="${path_name//bar/more}"
mv -v "$path_name" "$new_pathname"
new_filename="${file_name//foo/bar}"
mv -v "${new_pathname%/*}$file_name" "$new_pathname$new_filename"
没有使用额外的外部 tool/utility,除了您的脚本正在使用的那些。
删除 echo
如果您对 result/output 感到满意。
您可以使用 -execdir
到 运行 仅对相关目录中的文件名(基本名称)执行命令:
find . -depth -name '*foo*' -execdir bash -c 'mv -- "" "${1//foo/bar}"' _ {} \;
我正在编写一个将执行某些操作的脚本,其中一个操作是在文件名和目录名中查找所有出现的字符串,并将其替换为另一个字符串。
目前我有这个
find . -name "*foo*" -type f -depth | while read file; do
newpath=${file//foo/bar}
mv "$file" "$newpath"
done
只要文件路径不包含 foo
,这就可以正常工作,但不能保证。
我觉得解决这个问题的方法是先更改文件名,然后返回并更改目录名,但即便如此,如果您的结构包含多个目录 foo
在里面,将无法正常工作。
有没有办法使用内置的 macOS 工具来做到这一点? (我说内置,因为这个脚本将分发给我们组织中的其他一些人,它不能依赖任何要安装的包)。
将 path_name 与 file_name 分开,类似于
#!/usr/bin/env bash
while read -r file; do
path_name="${file%/*}"; printf 'Path is %s\n' "$path_name"
file_name="${file#"$path_name"}"; printf 'Filename is %s\n' "$file_name"
newpath="$path_name${file_name//foo/bar}"
echo mv -v "$file" "$newpath"
done < <(find . -name "*foo*" -type f)
也看看 basename
和 dirname
。
printf
只是为了显示路径和文件名。
脚本只是将 file_name 中的 foo
替换为 bar
,用 path_name 也可以完成,只需使用相同的语法即可。
newpath="${path_name//bar/more}${file_name//foo/bar}"
因此重命名 path_name 和 file_name。
或者像您的想法一样重命名 path_name 然后 file_name 也是一种选择。
path_name="${file%/*}"
file_name="${file#"$path_name"}"
new_pathname="${path_name//bar/more}"
mv -v "$path_name" "$new_pathname"
new_filename="${file_name//foo/bar}"
mv -v "${new_pathname%/*}$file_name" "$new_pathname$new_filename"
没有使用额外的外部 tool/utility,除了您的脚本正在使用的那些。
删除 echo
如果您对 result/output 感到满意。
您可以使用 -execdir
到 运行 仅对相关目录中的文件名(基本名称)执行命令:
find . -depth -name '*foo*' -execdir bash -c 'mv -- "" "${1//foo/bar}"' _ {} \;