【问题标题】:find and replace a word with another in all file names of a directory在目录的所有文件名中查找并替换一个单词
【发布时间】:2013-07-19 03:56:17
【问题描述】:

我正在尝试在我的目录(以及所有子目录)的所有文件名中将“所有者”一词替换为“用户”。

例如

owners_controller => users_controller
owner.rb => user.rb

任何帮助将不胜感激

【问题讨论】:

  • 我试过这个: grep -rl 'owner' 。 | xargs sed -i 's/owner/user/g' 但这仅适用于文件中的单词,而不适用于文件名本身
  • 试试这样的东西 find / -name 'program.c' |grep owner |xargs .

标签: linux shell grep


【解决方案1】:

使用find-exec 选项在名称中包含“所有者”的每个文件和子目录上调用rename

find path/to/my/directory/ -depth -name "*owner*" -exec /usr/bin/rename owner user {} \+

如果没有rename,可以使用mv 命令和bash 参数扩展:

find path/to/my/directory/ -depth -name "*owner*" -exec \
  bash -c 'mv "{}" $(old="{}"; new="${old##*/}"; echo "${old%/*}/${new/owner/user}")' \;

bash -c '...' 调用由单引号包围的单行上的 bash shell。单行代码充当mv 命令,将匹配文件名/子目录的基本名称中所有出现的“owner”重命名为“user”。

具体来说,find-exec 之后的每个 {} 替换为匹配的文件/子目录的路径名。这里mv 接受两个参数;第一个是{}(如前所述),第二个是从包含三个bash 命令的子shell $(...) 返回的字符串。这些 bash 命令使用parameter expansion techniques 重命名{} 的基本名称。

【讨论】:

  • 可能需要将-depth 选项设置为find,以防止重命名子目录时出现故障,导致在旧位置下无法再访问它的文件...
  • 我已经指定了-type f。很确定这会阻止子目录被传递给rename
  • 我可能误读了 OP 的“并且在所有子目录中”,这意味着子目录重命名是预期的......如果它真的只是要重命名的文件,那么 -depth 是不必要的(尽管它不会伤害任何东西)...
  • 你是对的;问题的措辞含糊不清。如果 OP 表示“文件名和子目录”,则应将 -type f 替换为 -depth
  • 抱歉,我的意思是“文件名和子目录”
【解决方案2】:

如果您没有安装rename,这应该是一个合理的选择(假设bash 作为您的shell):

while read entry
do
  mv "${entry}" "${entry/owner/user}"
done < <(find . -depth -name '*owner*' -print)

【讨论】: