如何在 shell 命令行脚本中重命名文件名 - 用空格替换下划线

如何在 shell 命令行脚本中重命名文件名 - 用空格替换下划线

我正在尝试重命名文件夹中的所有文件,并用空格替换下划线。

i.e. this_is_a_test --> this is a test

但不知怎的,我把引用搞乱了

> for file in * ; do echo mv -v $file $(echo $file | sed 's/_/\\ /g') ; done
mv -v this_is_a_test this\ is\ a\ test

看起来不错,但如果我删除“echo”,mv就会出现类似删除反斜杠的情况

> for file in * ; do mv -v $file $(echo $file | sed 's/_/\\ /g') ; done
mv: target ‘test’ is not a directory

有人能指出我的错误吗?

答案1

使用rename

rename -n 's/_/ /g' *

如果一切正常,请移除-n开关:

rename 's/_/ /g' *
~/tmp$ tree
.
├── file
├── file_1
├── file_2
├── file_3
└── file_with_underscores

0 directories, 5 files
~/tmp$ rename 's/_/ /g' *
~/tmp$ tree
.
├── file
├── file 1
├── file 2
├── file 3
└── file with underscores

0 directories, 5 files

答案2

有一个小错误。使用"$newfile"而不是$newfile。您需要使用"

这是正确的。

for file in * ; do mv -v "$file" "$(echo $file | sed 's/_/\\ /g')" ; done

如果您有文件名,this_is_a_test它会将文件重命名为this\ is\ a\ test

如果您想将文件重命名为this is a test。使用下面的代码,

for file in * ; do mv -v "$file" "$(echo $file | sed 's/_/ /g')" ; done

""在编写好的 shell 脚本时,使用内部变量是一种很好的做法。

答案3

您可以mv -v "$file" "$(echo $file | sed 's/_/\\ /g')"使用更简单的命令mv "$f" "${f//_/ }"

要将其添加到您的脚本中:

for f in * ; do mv "$f" "${f//_/ }" ; done

就是这样。

答案4

以下是 awk + ​​for 循环版本:

for filename in *; do NEWNAME=$(echo "$filename" | awk '{gsub("_"," "); print}'); mv "$filename" "$NEWNAME";done

以下是实际效果

$ ls                                                                                                                                                  

$ echo "TEST" | tee {foo,bar}_{yolo,swag}_{whatever,else}.txt                                                                                         
TEST

$ ls
bar_swag_else.txt      bar_yolo_else.txt      foo_swag_else.txt      foo_yolo_else.txt
bar_swag_whatever.txt  bar_yolo_whatever.txt  foo_swag_whatever.txt  foo_yolo_whatever.txt

$ for filename in *; do NEWNAME=$(echo "$filename" | awk '{gsub("_"," "); print}'); mv "$filename" "$NEWNAME";done                                    

$ ls
bar swag else.txt      bar yolo else.txt      foo swag else.txt      foo yolo else.txt
bar swag whatever.txt  bar yolo whatever.txt  foo swag whatever.txt  foo yolo whatever.txt

为了考虑换行符和可能的目录重命名,这里是典型的 IFS + find + read + while 循环构造。建议通过后,首先运行带有 的版本find . -type d -print0,因为如果您首先开始重命名文件,并且子目录包含下划线,则文件名不会更改。简而言之,先处理目录和子目录,然后再处理文件

$ ls
file_bar_swag.txt  file_bar_yolo.txt  file_test_swag.txt  file_test_yolo.txt  foo_bar_swag.txt  foo_bar_yolo.txt  foo_test_swag.txt  foo_test_yolo.txt  tester_dir

$ ls tester_dir/                                                                                                                                                                                         
ber_sweg_elze.txt  ber_sweg_whut.txt  ber_yelo_elze.txt  ber_yelo_whut.txt  fee_sweg_elze.txt  fee_sweg_whut.txt  fee_yelo_elze.txt  fee_yelo_whut.txt

$  find . -type d -print0 | while IFS="" read -r -d "" filename ; do NEWNAME=$(echo "$filename" | awk '{gsub("_"," "); print}'); mv "$filename" "$NEWNAME";done 
mv: ‘.’ and ‘./.’ are the same file

$ ls
file_bar_swag.txt  file_bar_yolo.txt  file_test_swag.txt  file_test_yolo.txt  foo_bar_swag.txt  foo_bar_yolo.txt  foo_test_swag.txt  foo_test_yolo.txt  tester dir

$  find . -type f -print0 | while IFS="" read -r -d "" filename ; do NEWNAME=$(echo "$filename" | awk '{gsub("_"," "); print}'); mv "$filename" "$NEWNAME";done                                          
mv: ‘./.yolo’ and ‘./.yolo’ are the same file

$ ls
file bar swag.txt  file bar yolo.txt  file test swag.txt  file test yolo.txt  foo bar swag.txt  foo bar yolo.txt  foo test swag.txt  foo test yolo.txt  tester dir

如您所见,有一个小问题 - 因为 find 命令也列出了当前目录(用 . 表示),所以该命令将创建一个副产品 - 一个以点为前导的文件。

! -path .在处理目录时添加即可解决问题

$ find . ! -path .  -type d -print0 | while IFS="" read -r -d "" filename ; do NEWNAME=$(echo "$filename" | awk '{gsub("_"," "); print}'); mv "$filename" "$NEWNAME";done                                

$ find .  -type f -print0 | while IFS="" read -r -d "" filename ; do NEWNAME=$(echo "$filename" | awk '{gsub("_"," "); print}'); mv "$filename" "$NEWNAME";done                                          

$ ls
file bar swag.txt  file bar yolo.txt  file baz swag.txt  file baz yolo.txt  foo bar swag.txt  foo bar yolo.txt  foo baz swag.txt  foo baz yolo.txt  tester dir

$ ls "tester dir"
file bar.txt  file baz.txt  foo bar.txt  foo baz.txt

$ ls -a
.  ..  file bar swag.txt  file bar yolo.txt  file baz swag.txt  file baz yolo.txt  foo bar swag.txt  foo bar yolo.txt  foo baz swag.txt  foo baz yolo.txt  tester dir

相关内容