Как удалить последние символы в имени файла с помощью Bash? - PullRequest
1 голос
/ 28 мая 2019

У меня есть несколько .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

Что я делаю неправильно и как я могу переименовать этифайлы

Ответы [ 3 ]

4 голосов
/ 28 мая 2019

Вы заполняете переменную i выводом find, но ссылаетесь на переменную file , которая не объявлена, в вызове mv. Таким образом, он расширяется до mv -f '' '', поэтому вы получаете Нет такого файла или каталога ошибка.

Вам лучше сделать это так:

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
1 голос
/ 28 мая 2019

Для многих людей это может быть необычное решение, но для меня это типичная работа с vi.То, что многие могут не помнить, вы можете передать содержимое буфера vi через оболочку, даже с выводом отладки (sh -x).

Что я делаю в таких или подобных ситуациях, где я не хочутратить слишком много времени на размышления о классных регулярных выражениях или хитростях с оболочкой ... прагматичный способ ... 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, то это идет ослепительно быстро, и у вас есть дополнительное преимущество, заключающееся в том, что у вас есть все возможности сохранять инструкции в файл для целей документирования.или разработать вещи для создания сценария и т. д.

0 голосов
/ 28 мая 2019

Вы начинаете с 'i', но затем ссылаетесь на 'f'. Попробуйте это:

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