Find and replace filename recursively in a directory
I want to rename all the files in a folder which starts with 123_xxx.txt to xxx.txt . For example, my directory has:
123_xxx.txt 123_yyy.txt 123_zzz.txt
I have seen some useful bash scripts in this forum but I’m still confused how to use it for my requirement. Let us suppose I use:
for file in `find -name '123_*.txt'` ; do mv $file ; done
15 Answers 15
find . -name '123_*.txt' -type f -exec sh -c ' for f; do mv "$f" "$/$" done' sh <> +
No pipes, no reads, no chance of breaking on malformed filenames, no non-standard tools or features.
This is making use of parameter expansion to strip the basename from the end of the path, then append a new name which has had the prefix up to 123_ removed. The two operators to read about are % and ## , the rest is simple globbing.
find . -name "123*.txt" -exec rename 's/^123_//' <> ";"
will do it. No AWK, no for, no xargs needed, but rename, a very useful command from the Perl lib. It is not always included with Linux, but is easy to install from the repos.
This is superior to the overkill awk and looping answers above for those people who have the perl rename .
To add to this, the use of find is unnecessary if you’re only talking about files in a single directory. It’s always best to keep it as simple as possible, so you can just do rename ‘s/^123_//’ * and it’ll do the exact same thing. Cheers.
@HodorTheCoder And if you’ve got globstar set in bash ( shopt -s globstar ), you can do it recursively: rename ‘s/^123_//’ **/*
In case you want to replace string in file name called foo to bar you can use this in linux ubuntu, change file type for your needs
find -name "*foo*.filetype" -exec rename 's/foo/bar/' <> ";"
This really worked and is simple. How can I make this replace names of files in directories recursively.
@madu Find searches recursively into directories by default. If you wanted it to only search the current directory, you would add a -maxdepth 1 flag before the -name … flag.
you could check ‘rename’ tool
kent$ tree . |-- 123_a.txt |-- 123_b.txt |-- 123_c.txt |-- 123_d.txt |-- 123_e.txt `-- u |-- 123_a.txt |-- 123_b.txt |-- 123_c.txt |-- 123_d.txt `-- 123_e.txt 1 directory, 10 files kent$ find . -name '123_*.txt'|awk ''|sh kent$ tree . |-- a.txt |-- b.txt |-- c.txt |-- d.txt |-- e.txt `-- u |-- a.txt |-- b.txt |-- c.txt |-- d.txt `-- e.txt 1 directory, 10 files
You should mention the homonym trap: you talk about special rename command that usurps the name of rename from util-linux (which does not deal with regular expressions).
The rename example isn’t recursive. The find example is, but it needlessly doesn’t use rename for renaming. And it pipes a generated script to sh , which is icky.
Thanks, is it possible for me to modify the filename to all lower cases after the rename? i mean.. any Xxx.txt should be xxx.txt finally?
To expand on Sorpigal’s answer, if you want to replace the 123_ with hello_ , you could use
find . -name '123*.txt' -type f -exec bash -c 'mv "$1" "$"' -- <> \;
A slight variation on Kent’s that doesn’t require gawk and is a little bit more readable, (although, thats debatable..)
Using rename from util-linux 2.28.2 I had to use a different syntaxt:
find -name "*.txt" -exec rename -v "123_" "" <> ";"
Provided you don’t have newlines in your filenames:
find -name '123_*.txt' | while IFS= read -r file; do mv "$file" "$"; done
For a really safe way, provided your find supports the -print0 flag (GNU find does):
find -name '123_*.txt' -print0 | while IFS= read -r -d '' file; do mv "$file" "$"; done
You can make a little bash script for that. Create a file named recursive_replace_filename with this content :
#!/bin/bash if test $# -lt 2; then echo "usage: `basename $0` " fi for file in `find . -name "*$1*" -type f`; do mv "'$file'" "$" done
$ chmod +x recursive_replace_filename $ ./recursive_replace_filename 123_ ""
Keep note that this script can be dangerous, be sure you know what it’s doing and in which folder you are executing it, and with which arguments. In this case, all files in the current folder, recursively, containing 123_ will be renamed.
Tried the answer above but it didn’t work for me cause i had the string inside folders and files name at the same time so here is what i did the following bash script:
for fileType in d f do find -type $fileType -iname "stringToSearch*" |while read file do mv $file $( sed -r "s/stringToSearch/stringToReplaceWith/"
First i began by replacing inside folders name then inside files name.
Worked well for me with spaces in the names of files. Just make sure you quote both vars in the mv line to work with spaces
Here's the only solution to date that works:
find-rename-recursive --pattern '123_' --string '' -- . -type f -name "123_*"
All other solutions don't work for me--some even deleted files!
If the names are fixed you can visit each directory and perform the renaming in a subshell (to avoid changing the current directory) fairly simply. This is how I renamed a bunch of new_paths.json files each to paths.json :
for file in $(find root_directory -name new_paths.json) do (cd $(dirname $file) ; mv new_paths.json paths.json) done
using the examples above, i used this to replace part of the file name. this was used to rename various data files in a directory, due to a vendor changing names.
find . -name 'o3_cloudmed_*.*' -type f -exec bash -c 'mv "$1" "$"' -- <> \;
Below, the find command searches recursively in the tree from the directory passed as first parameter (here it is the current directory "."). The following parameters are predicates to filter the files we are looking for. The "-name" predicate is a pattern to which the current file name must match (here we want manage only filenames beginning with '123_' and terminating with '.txt'. The "-type" filters the type of the file ('f' means regular file, 'd' would mean directory. ). The "-exec" predicate runs a command line into which '<>' is the current file name and the ';' terminates the command.
find . -name '123_*.txt' -type f -exec bash -c 'name=<>;mv $name $' \;
Как переименовать файл Linux
Переименование файла linux - очень простая операция, но для новичков в Linux эта задача может оказаться сложной. Также здесь есть несколько нюансов и возможностей, которые желательно знать уже опытным пользователям, например, массовое переименование. В графическом интерфейсе все делается очень просто, но настоящую гибкость дает терминал.
В этой статье мы рассмотрим как переименовать файл в Linux с помощью терминала, рассмотрим такие возможности, как массовое пакетное переименование файлов, а также регулярные выражения.
Как переименовать файл в Linux с помощью mv
В Linux существует замечательная стандартная утилита mv, которая предназначена для перемещения файлов. Но по своей сути перемещение - это то же самое, что и переименование файла linux, если выполняется в одной папке. Давайте сначала рассмотрим синтаксис этой команды:
$ mv опции файл-источник файл-приемник
Теперь рассмотрим основные опции утилиты, которые могут вам понадобиться:
- -f - заменять файл, если он уже существует;
- -i - спрашивать, нужно ли заменять существующие файлы;
- -n - не заменять существующие файлы;
- -u - заменять файл только если он был изменен;
- -v - вывести список обработанных файлов;
Чтобы переименовать файл linux достаточно вызвать утилиту без дополнительных опций. Просто передав ей имя нужного файла и новое имя:
Как видите, файл был переименован. Вы также можете использовать полный путь к файлу или переместить его в другую папку:
mv /home/sergiy/test/newfile /home/sergiy/test/file1
Обратите внимание, что у вас должны быть права на запись в ту папку, в которой вы собираетесь переименовывать файлы. Если папка принадлежит другому пользователю, возможно, нужно будет запускать программу через sudo. Но в таком случае лучше запускать с опцией -i, чтобы случайно ничего не удалить.
Переименование файлов Linux с помощью rename
В Linux есть еще одна команда, которая позволяет переименовать файл. Это rename. Она специально разработана для этой задачи, поэтому поддерживает такие вещи, как массовое переименование файлов linux и использование регулярных выражений. Синтаксис утилиты тоже сложнее:
$ rename опции 's/ старое_имя / новое_имя ' файлы
$ rename опции старое_имя новое_имя файлы
В качестве старого имени указывается регулярное выражение или часть имени которую нужно изменить, новое имя указывает на что нужно заменить. Файлы - те, которые нужно обработать, для выбора файлов можно использовать символы подставки, такие как * или ?.
- -v - вывести список обработанных файлов;
- -n - тестовый режим, на самом деле никакие действия выполнены не будут;
- -f - принудительно перезаписывать существующие файлы;
Например, переименуем все htm файлы из текущей папки в .html:
Символ звездочки означает, что переименование файлов linux будет выполнено для всех файлов в папке. В регулярных выражениях могут применяться дополнительные модификаторы:
- g (Global) - применять ко всем найденным вхождениям;
- i (Case Censitive) - не учитывать регистр.
Модификаторы размещаются в конце регулярного выражения, перед закрывающей кавычкой. Перед тем, как использовать такую конструкцию, желательно ее проверить, чтобы убедиться, что вы не допустили нигде ошибок, тут на помощь приходит опция -n. Заменим все вхождения DSC на photo в именах наших фотографий:
rename -n 's/DSC/photo/gi' *.jpeg
Будут обработаны DSC, DsC и даже dsc, все варианты. Поскольку использовалась опция -n, то утилита только выведет имена изображений, которые будут изменены.
Можно использовать не только обычную замену, но и полноценные регулярные выражения чтобы выполнить пакетное переименование файлов linux, например, переделаем все имена в нижний регистр:
Из этого примера мы видим, что даже если такой файл уже существует, то он перезаписан по умолчанию не будет. Не забывайте использовать опцию -n чтобы ничего случайно не повредить.
Переименование файлов в pyRenamer
Если вы не любите использовать терминал, но вам нужно массовое переименование файлов Linux, то вам понравится утилита pyrenamer. Это графическая программа и все действия здесь выполняются в несколько щелчков мыши. Вы можете установить ее из официальных репозиториев:
sudo apt install pyrenamer
В окне программы вы можете видеть дерево файловой системы, центральную часть окна, где отображаются файлы, которые будут изменены, а также панель для указания параметров переименования.
Вы можете удалять или добавлять символы, переводить регистр, автоматически удалять пробелы и подчеркивания. У программы есть подсказки, чтобы сделать ее еще проще:
Опытным пользователям понравится возможность pyRenamer для переименования мультимедийных файлов из их метаданных. Кроме того, вы можете переименовать один файл если это нужно. Эта утилита полностью реализует функциональность mv и remove в графическом интерфейсе.
Выводы
В этой статье мы рассмотрели как переименовать файл в консоли linux. Конечно, есть и другие способы, например, написать скрипт, или использовать файловые менеджеры. А как вы выполняете сложные операции по переименованию? Напишите в комментариях!
Обнаружили ошибку в тексте? Сообщите мне об этом. Выделите текст с ошибкой и нажмите Ctrl+Enter.