Reputation: 2126
I have several .txt
files in a folder, their names look as follows:
file1.txt
file2.txt
file2.txt_newfile.txt
file3.txt
file4.txt
file4.txt_newfile.txt
file5.txt_newfile.txt
...
I am trying to remove _newfile.txt
from the file names. If the file is present, it should be overwritten by the new file (e.g. file2.txt
will be replaced, but file5.txt
will just be renamed).
Expected output:
file1.txt
file2.txt # this was file2.txt_newfile.txt
file3.txt
file4.txt # file4.txt_newfile.txt
file5.txt #file5.txt_newfile.txt
...
I tried the following code:
for i in $(find . -name "*_newfile.txt" -print); do
mv -f "$file" "${file%????????????}"
done
However, I get the following error:
mv: rename to : No such file or directory
What am I doing wrong and how can I rename these files?
Upvotes: 1
Views: 964
Reputation: 206
For many people maybe an unusual solution, but for me this is a typical vi job. What many people might not remember, you can pipe the content of the vi buffer through a shell, even with debugging output (sh -x).
What I do in such or similar situations, where I do not want to loose too much time thinking about cool regular expressions or shell trickeries ... the pragmatic way ... vi supports you ;-)
Here we go:
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
Finally quit vi.
It looks maybe on the 1st glimpse like many steps, but if you know vi, then this goes blindingly fast and you have the additional advantage that you have all possibilities to save the instructions to a file for documentation purposes or to work things out to create a script, etc.
Upvotes: 1
Reputation: 50750
You're populating variable i with find
's output, but referencing variable file, which is undeclared, in mv
invocation. So it expands to mv -f '' ''
, that's why you get a No such file or directory error.
You better do that like this:
find -type f -name '*_newfile.txt' -exec sh -c '
for fname; do
mv -- "$fname" "${fname%_newfile.txt}"
done' _ {} +
If these files are all in the same folder, you don't even need find
, just a for loop will do the same:
for fname in *_newfile.txt; do
mv -- "$fname" "${fname%_newfile.txt}"
done
Upvotes: 5