Переименование части названия файла

На самом деле это единственный раздел про unix на этом форуме

Модераторы: /dev/random, Модераторы разделов

Ответить
fireboltgp
Сообщения: 62
ОС: openSUSE 12.3 KDE 4.10.3

Переименование части названия файла

Сообщение fireboltgp »

Приветствую и благодарю всех, появивших интерес!

Задача моя очень проста: переименовать "name-daily-backup.tgz" в "name-weekly-backup.tgz" (сменить daily на weekly в названии файлов). Да только вот гугл не нашел прямого ответа на мой вопрос. Попытки прочесть man sed'a навели страх, и тратить время на изучение пугающего не хочется, ибо слишком долго :mellow: Прошу показать конкретные параметры для sed'a на примере

Код: Выделить всё

ls *.tgz | sed 's/regexp/replacement/' | sh
:)

Другие варианты выполнения задачи тоже интересны
Спасибо сказали:
Аватара пользователя
SLEDopit
Модератор
Сообщения: 4823
Статус: фанат консоли (=
ОС: GNU/Debian, RHEL

Re: Переименование части названия файла

Сообщение SLEDopit »

Не надо так делать. Парсить ls сам по себе плохо.
Ну и формировать команды sed'ом тогда, когда без этого можно вполне обойтись, тоже не есть хорошо (и, кстати, последний пайп с sh вполне можно заменить на sed'овскую команду е, если sed gnu'тый).

В данном случае я бы обратил внимание на команду rename. В моём дистрибутиве то, что вы хотите выглядело бы так:

Код: Выделить всё

rename 's/daily/weekly/' *.tgz
Однако перед применением, всё же почитайте man rename, поскольку в разных дистрибутивах устновлены разные rename (не разные версии, а именно разные программы с одинаковым названием). Могут быть отличия.

Ну, или на худой конец, переименовал бы на чистом bash:

Код: Выделить всё

for file in *.tgz ; do mv -v "$file" "${file/daily/weekly}" ; done
UNIX is basically a simple operating system, but you have to be a genius to understand the simplicity. © Dennis Ritchie
The more you believe you don't do mistakes, the more bugs are in your code.
Спасибо сказали:
fireboltgp
Сообщения: 62
ОС: openSUSE 12.3 KDE 4.10.3

Re: Переименование части названия файла

Сообщение fireboltgp »

SLEDopit писал(а):
22.10.2013 13:48
Однако перед применением, всё же почитайте man rename, поскольку в разных дистрибутивах устновлены разные rename (не разные версии, а именно разные программы с одинаковым названием). Могут быть отличия.


Вот блин, как неудобно. В openSUSE (где тестирую) rename явно не тот, что в Debian (где будет работать).

Благодарю вас за подробный ответ! Попробую применить.
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 20752
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Переименование части названия файла

Сообщение Bizdelnick »

fireboltgp писал(а):
22.10.2013 13:54
В openSUSE (где тестирую) rename явно не тот, что в Debian (где будет работать).

Возможно, в openSUSE есть оба варианта rename, как и в Debian. Тот rename, который используется в Debian по умолчанию, входит в пакет perl под названием prename.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
fireboltgp
Сообщения: 62
ОС: openSUSE 12.3 KDE 4.10.3

Re: Переименование части названия файла

Сообщение fireboltgp »

Пришел босс и помог таки разобраться. В итоге сделали:

Код: Выделить всё

find '/home/user/test/' -maxdepth 5 -name \*.tgz -mtime $keeptime | sed 's/\(.*\)daily\(.*\)$/mv "&" "\1weekly\2"/' | sh


Благодарен всем! Уверен, эта тема окажется многим полезной.
Спасибо сказали:
Аватара пользователя
Фантом
Сообщения: 452
ОС: openSUSE

Re: Переименование части названия файла

Сообщение Фантом »

fireboltgp писал(а):
22.10.2013 13:54
Вот блин, как неудобно. В openSUSE (где тестирую) rename явно не тот, что в Debian (где будет работать).

В openSUSE это делается командой rename daily weekly *daily*

P.S. В предположении, что все эти файлы в одном каталоге. Обход каталогов, если надо - стандартно с помощью find.
Спасибо сказали:
liaonau
Сообщения: 390
ОС: gentoo

Re: Переименование части названия файла

Сообщение liaonau »

fireboltgp писал(а):
22.10.2013 15:12
Пришел босс и помог таки разобраться. В итоге сделали:

Код: Выделить всё

find '/home/user/test/' -maxdepth 5 -name \*.tgz -mtime $keeptime | sed 's/\(.*\)daily\(.*\)$/mv "&" "\1weekly\2"/' | sh


Благодарен всем! Уверен, эта тема окажется многим полезной.

Очень нестандартный способ.
Во первых, есть xargs и опция -exec у find. В зависимости от версии rename в дистрибутиве:

Код: Выделить всё

find /some/dir -name "*daily*tgz"|xargs rename daily weakly
find /some/dir -name "*daily*tgz"|xargs perl-rename 's/daily/weakly/'
find /some/dir -name "*daily*tgz" -exec rename daily weakly {} \;

Это если в общем случае надо сформировать команду из выхлопа find. Во вторых, perl-rename принимает имена из пайпа, поэтому достаточно:

Код: Выделить всё

find /some/dir/ -name "*daily*tgz"|perl-rename 's/daily/weakly/'

Оптимальный вариант, запускающий интерпретатор perl (или бинарник rename) один раз (вдруг файлов тысячи?):

Код: Выделить всё

perl-rename 's/daily/weakly/' $(find /some/dir -name "*daily*tgz")
rename daily weakly $(find /some/dir -name "*daily*tgz")

В третьих, уже говорилось, что достаточно просто bash.

Хотя все эти способы (и ваш тоже) не сработают если в имени директории есть слово daily.
Вот так, вроде бы, работает:

Код: Выделить всё

perl-rename 's|daily(?!.*/.*)|weakly|' $(find /some/dir -name "*daily*tgz" -type f)
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 20752
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Переименование части названия файла

Сообщение Bizdelnick »

liaonau писал(а):
22.10.2013 22:27
Оптимальный вариант, запускающий интерпретатор perl (или бинарник rename) один раз (вдруг файлов тысячи?):

Код: Выделить всё

perl-rename 's/daily/weakly/' $(find /some/dir -name "*daily*tgz")
rename daily weakly $(find /some/dir -name "*daily*tgz")

Или find /some/dir -name "*daily*tgz" -exec prename 's/daily/weakly/' {} \+.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
fireboltgp
Сообщения: 62
ОС: openSUSE 12.3 KDE 4.10.3

Re: Переименование части названия файла

Сообщение fireboltgp »

liaonau

Я поражен количеством предложенных вариантов! Супер!
Использовал я этот нестандартный метод по той простой причине, что гугл его только и выдает. Поэтому основывался на нем, его и довел до нужного результата. Ваши, конечно, предложения проще.
Спасибо сказали:
fireboltgp
Сообщения: 62
ОС: openSUSE 12.3 KDE 4.10.3

Re: Переименование части названия файла

Сообщение fireboltgp »

В общем, для Debian приемлемо следующее:

Код: Выделить всё

find /some/dir -name "*.tgz" | xargs rename 's/daily/weakly/'

find /some/dir -name "*.tgz" | rename 's/daily/weakly/'

find /some/dir -name "*.tgz" -exec rename 's/daily/weakly/' {} \;


Первый - не имеет мысла, второй - через трубы, третий - все в одном. Использую третий, чувстуется, что он понадежней.

Спасибо сказали:
Аватара пользователя
nerve
Сообщения: 280
ОС: OpenBSD

Re: Переименование части названия файла

Сообщение nerve »

добавлю еще один вариант так как в CentOS rename не захотел работать. нужно было по маске скопировать много файлов сохранив часть имени файла и заменив другую часть.

Код: Выделить всё

for FILE in OLD*; do cp $FILE $(echo $FILE | sed -e 's/OLD/NEW/g'); done

Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 20752
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Переименование части названия файла

Сообщение Bizdelnick »

nerve писал(а):
26.11.2013 18:25
в CentOS rename не захотел работать

А Вы man rename посмотреть не забыли? (-:
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
Аватара пользователя
nerve
Сообщения: 280
ОС: OpenBSD

Re: Переименование части названия файла

Сообщение nerve »

предложите работающий вариант)
man rename и rename --help дают весьма скромное понятие как им воспользоваться в центоси.
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 20752
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Переименование части названия файла

Сообщение Bizdelnick »

nerve писал(а):
27.11.2013 00:40
man rename и rename --help дают весьма скромное понятие как им воспользоваться в центоси.

Главное - чтобы они давали понятие, rename это из util-linux, или же prename. Это две совершенно разные программы с разным синтаксисом, хотя и служащие для одной цели. Подозреваю, что обе они в CentOS должны быть.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current
Контактная информация:

Re: Переименование части названия файла

Сообщение drBatty »

Bizdelnick писал(а):
27.11.2013 00:51
Подозреваю, что обе они в CentOS должны быть.

ЕМНИП там как в слаке: по дефолту только простая из util-linux. Перловую можно поставить дополнительно.

Но ИМХО для задачи ТСа ставить перловую версию не нужно. Зачем она здесь, если нужно просто как здесь: Переименование части названия файла
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
V112
Сообщения: 8

Re: Переименование части названия файла

Сообщение V112 »

Код:

find dir -type f -name "*.tgz" | while read i do dirname="$(dirname "${i}")" oldname="$(basename "${i}")" newname="$(echo "${oldname}" | sed 's/daily/weakly/')" if [ "${oldname}" != "${newname}" ] then mv "${i}" "${dirname}/${newname}" fi done
Спасибо сказали:
Аватара пользователя
SLEDopit
Модератор
Сообщения: 4823
Статус: фанат консоли (=
ОС: GNU/Debian, RHEL

Re: Переименование части названия файла

Сообщение SLEDopit »

V112
с более менее приличным списком файлов ваш вариант будет работать чертовски долго, если сравнивать с решениями целиком на find.
UNIX is basically a simple operating system, but you have to be a genius to understand the simplicity. © Dennis Ritchie
The more you believe you don't do mistakes, the more bugs are in your code.
Спасибо сказали:
Аватара пользователя
sgfault
Сообщения: 586
Статус: -
Контактная информация:

Re: Переименование части названия файла

Сообщение sgfault »

SLEDopit писал(а):
27.11.2013 14:27
V112
с более менее приличным списком файлов ваш вариант будет работать чертовски долго, если сравнивать с решениями целиком на find.

Целиком на find - это с -exec что ли? Среди всех предложенных вариантов с -exec только один, незаслуженно оставленный без внимания автором темы, будет работать быстрее. Остальные - также медленны и печальны, как и скрипт:

Код: Выделить всё

$ seq 1 10000 | sed 's/^/daily./' | xargs touch
$ find . -type f -name 'daily*' | wc -l
10000
$ time find . -type f -name 'daily*' -exec rename 's/daily/weekly/' {} \;

real    2m56.762s
user    2m16.505s
sys     0m22.553s
$ find . -type f -name 'weekly*' | wc -l
10000

и

Код: Выделить всё

$ seq 1 10000 | sed 's/^/daily./' | xargs touch
$ find . -type f -name 'daily*' | wc -l
10000
$ cat ./t.sh
#!/bin/sh

find -type f -name "daily.*" |
while read i
do
dirname="$(dirname "${i}")"
oldname="$(basename "${i}")"
newname="$(echo "${oldname}" | sed 's/daily/weekly/')"
if [ "${oldname}" != "${newname}" ]
then
mv "${i}" "${dirname}/${newname}"
fi
done
$ time ./t.sh

real    1m34.802s
user    0m0.892s
sys     0m6.864s
$ find . -type f -name 'weekly*' | wc -l
10000

Скрипт даже оказался почти в два раза быстрее: 2.56 минуты против 1.34 минуты у скрпта, но оба эти результата, конечно, целая вечность по сравнению с '-exec {} \+' или '| xargs rename':

Код: Выделить всё

$ seq 1 10000 | sed 's/^/daily./' | xargs touch
sgf@shilvana:~/test$ find . -type f -name 'daily*' | wc -l
10000
$ time find . -type f -name 'daily*' -exec rename 's/daily/weekly/' {} \+

real    0m0.460s
user    0m0.272s
sys     0m0.180s
$
$ find . -type f -name 'weekly*' | wc -l
10000

Код: Выделить всё

$ seq 1 10000 | sed 's/^/daily./' | xargs touch
$ find . -type f -name 'daily*' | wc -l
10000
$ time find . -type f -name 'daily*' | xargs rename 's/daily/weekly/'

real    0m0.469s
user    0m0.256s
sys     0m0.208s
$ find . -type f -name 'weekly*' | wc -l
10000


В результате, вариант, который автор назвал "не имеет смысла" (#10), обгоняет выбранный им в 5.5 раз всего лишь на 10к файлов. Хех.. :huh: и количество вызовов команды-таки остается решающим.

Upd. Исправил неправильный копипаст.
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current
Контактная информация:

Re: Переименование части названия файла

Сообщение drBatty »

sgfault писал(а):
30.11.2013 18:50
но оба эти результата, конечно, целая вечность по сравнению с '-exec {} \+' или '| xargs rename':

а если попробовать rename из util-linux? ИМХО тогда ещё быстрее будет.
sgfault писал(а):
30.11.2013 18:50
и количество вызовов команды-таки остается решающим.

неудивительно.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Ответить