如何使用 Bash 删除文件名中的最后一个字符?

How to remove the last characters in a file name using Bash?

我在一个文件夹中有几个 .txt 个文件,它们的名称如下:

file1.txt
file2.txt
file2.txt_newfile.txt
file3.txt
file4.txt
file4.txt_newfile.txt
file5.txt_newfile.txt
...

我正在尝试从文件名中删除 _newfile.txt。如果文件存在,它应该被新文件覆盖(例如 file2.txt 将被替换,但 file5.txt 将被重命名)。

预期输出:

file1.txt
file2.txt # this was file2.txt_newfile.txt
file3.txt
file4.txt # file4.txt_newfile.txt
file5.txt #file5.txt_newfile.txt
...

我尝试了以下代码:

for i in $(find . -name "*_newfile.txt" -print); do 
mv -f "$file" "${file%????????????}"
done

但是,我收到以下错误:

mv: rename  to : No such file or directory

我做错了什么以及如何重命名这些文件?

您正在使用 find 的输出填充变量 i,但引用了未声明的变量 file,在 mv 调用中。所以它扩展为 mv -f '' '',这就是为什么你会收到 No such file or directory 错误。

你最好这样做:

find -type f -name '*_newfile.txt' -exec sh -c '
for fname; do
  mv -- "$fname" "${fname%_newfile.txt}"
done' _ {} +

如果这些文件都在同一个文件夹,你甚至不需要find,只需要一个for循环就可以做到:

for fname in *_newfile.txt; do
  mv -- "$fname" "${fname%_newfile.txt}"
done

对很多人来说这可能是一个不寻常的解决方案,但对我来说这是一个典型的 vi 工作。 许多人可能不记得的是,您可以通过 shell 管道传输 vi 缓冲区的内容,即使使用调试输出 (sh -x)。

我在这种或类似情况下所做的事情,我不想浪费太多时间思考很酷的正则表达式或 shell 诡计......务实的方式...... vi 支持你;- )

开始吧:

1. enter directory with those files that you want to rename
2. start vi
3. !!ls *_newfile.txt
note: the !! command prompts you at the bottom to enter a command, the output of the ls command fills the vi buffer
4. dG
deletes all lines from your position 1 to the end of buffer, with a copy of it in the yank buffer
5. PP
paste 2 times the yank buffer
6. !G sort
!G prompts you at the bottom to pipe the buffer through sort
now you have all the lines double to save the work of typing filename again
7. with a combination of JkJk
you join the lines, so you have now the filename 2 times in a line like here:
file2.txt_newfile.txt file2.txt_newfile.txt
8. now add a mv command at the beginning of each line using an ex command
:%s/^/mv /
9. now remove the not needed trailing "_newfile.txt", again with an ex command
:%s/_newfile.txt$//
Now you have i.e. the following line(s) in the vi buffer:
mv file2.txt_newfile.txt file2.txt
10 back to line 1 to that you feed the whole buffer to the shell in the next step
1G
11. feed the shell commands to the shell and show some debug command
!G sh -x
12. check the results in the folder within vi, you will get the output of the ls command into the buffer
!!ls -l

终于退出vi了

乍看之下可能有很多步骤,但如果您了解 vi,那么这将变得非常快,而且您还有一个额外的优势,即您可以将所有说明保存到文件中以供文档使用或解决问题以创建脚本等