Linux часть имени файла

unixforum.org

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

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

Другие варианты выполнения задачи тоже интересны

SLEDopit Модератор Сообщения: 4814 Статус: фанат консоли (= ОС: GNU/Debian, RHEL

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

Сообщение SLEDopit » 22.10.2013 13:48

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

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

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

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

for file in *.tgz ; do mv -v "$file" "$" ; 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.

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

Сообщение fireboltgp » 22.10.2013 13:54

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

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

Благодарю вас за подробный ответ! Попробую применить.

Bizdelnick Модератор Сообщения: 20385 Статус: nulla salus bello ОС: Debian GNU/Linux

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

Сообщение Bizdelnick » 22.10.2013 14:05

Возможно, в openSUSE есть оба варианта rename, как и в Debian. Тот rename, который используется в Debian по умолчанию, входит в пакет perl под названием prename.

в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик

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

Сообщение fireboltgp » 22.10.2013 15:12

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

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

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

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

Сообщение Фантом » 22.10.2013 19:31

Читайте также:  Сгенерировать хеш пароля linux

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

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

P.S. В предположении, что все эти файлы в одном каталоге. Обход каталогов, если надо — стандартно с помощью find.

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

Сообщение liaonau » 22.10.2013 22:27

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

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 Модератор Сообщения: 20385 Статус: nulla salus bello ОС: Debian GNU/Linux

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

Сообщение Bizdelnick » 22.10.2013 23:42

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

perl-rename 's/daily/weakly/' $(find /some/dir -name "*daily*tgz") rename daily weakly $(find /some/dir -name "*daily*tgz")
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик

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

Сообщение fireboltgp » 23.10.2013 07:09

Я поражен количеством предложенных вариантов! Супер!
Использовал я этот нестандартный метод по той простой причине, что гугл его только и выдает. Поэтому основывался на нем, его и довел до нужного результата. Ваши, конечно, предложения проще.

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

Сообщение fireboltgp » 23.10.2013 07:44

В общем, для 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/' <> \;

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

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

Сообщение nerve » 26.11.2013 18:25

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

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

Bizdelnick Модератор Сообщения: 20385 Статус: nulla salus bello ОС: Debian GNU/Linux

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

Сообщение Bizdelnick » 26.11.2013 18:38

в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик

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

Сообщение nerve » 27.11.2013 00:40

Читайте также:  Intel rst drivers linux

предложите работающий вариант)
man rename и rename —help дают весьма скромное понятие как им воспользоваться в центоси.

Bizdelnick Модератор Сообщения: 20385 Статус: nulla salus bello ОС: Debian GNU/Linux

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

Сообщение Bizdelnick » 27.11.2013 00:51

Главное — чтобы они давали понятие, rename это из util-linux, или же prename. Это две совершенно разные программы с разным синтаксисом, хотя и служащие для одной цели. Подозреваю, что обе они в CentOS должны быть.

в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик

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

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

Сообщение drBatty » 27.11.2013 06:54

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

Но ИМХО для задачи ТСа ставить перловую версию не нужно. Зачем она здесь, если нужно просто как здесь: Переименование части названия файла

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

Сообщение V112 » 27.11.2013 13:30

find dir -type f -name «*.tgz» | while read i do dirname=»$(dirname «$«)» oldname=»$(basename «$«)» newname=»$(echo «$» | sed ‘s/daily/weakly/’)» if [ «$» != «$» ] then mv «$» «$/$» fi done

SLEDopit Модератор Сообщения: 4814 Статус: фанат консоли (= ОС: GNU/Debian, RHEL

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

Сообщение SLEDopit » 27.11.2013 14:27

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.

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

Сообщение sgfault » 30.11.2013 18:50

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 "$")" oldname="$(basename "$")" newname="$(echo "$" | sed 's/daily/weekly/')" if [ "$" != "$" ] then mv "$" "$/$" 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к файлов. Хех.. и количество вызовов команды-таки остается решающим.

Читайте также:  Arch linux установка на виртуальную

Upd. Исправил неправильный копипаст.

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

Источник

Renaming part of a filename [duplicate]

That was too easy. Awesome. 🙂 For anyone on windows PowerTools has PowerRename that has a lot of options and works really well.

for file in *.dat ; do mv $file $ ; done 

No rename or sed needed. Just bash parameter expansion.

If file names are having space, you should use quote. See snippet below. for file in *.dat ; do mv «$file» «$» ; done

Something like this will do it. The for loop may need to be modified depending on which filenames you wish to capture.

for fspec1 in DET01-ABC-5_50-*.dat ; do fspec2=$(echo $ | sed 's/-ABC-/-XYZ-/') mv $ $ done 

You should always test these scripts on copies of your data, by the way, and in totally different directories.

for osx this the stuff. rename looks cool, but a brew install of rename seems to install a perl script which didn’t work per the example above. Some googling indicated that rename isn’t available on all linux vars and that there is infact a perl version floating about. I got about 10 minutes into trying to sort out the differences and decides — you know this answer is just easy enough :).

And also to use for so you can loop through your file entries http://www.cyberciti.biz/faq/bash-for-loop/

Your command will look something like this, I don’t have a term beside me so I can’t check

for i in `dir` do mv $i `echo $i | sed '/orig/new/g'` 

I like to do this with sed. In you case:

for x in DET01-*.dat; do echo $x | sed -r 's/DET01-ABC-(.+)\.dat/mv -v "\0" "DET01-XYZ-\1.dat"/' done | sh -e 

It is best to omit the «sh -e» part first to see what will be executed.

Are you trying with or without the «sh -e»? If you are trying without it is not supposed to. It just prints what will be executed («mv -v . . » lines) as a chance to check if everything is ok. If you like what you see add the «sh -e».

All of these answers are simple and good. However, I always like to add an interactive mode to these scripts so that I can find false positives.

if [[ -n $inInteractiveMode ]] then echo -e -n "$oldFileName => $newFileName\nDo you want to do this change? [Y/n]: " read run [[ -z $run || "$run" == "y" || "$run" == "Y" ]] && mv "$oldFileName" "$newFileName" fi 

Or make interactive mode the default and add a force flag (-f | —force) for automated scripts or if you’re feeling daring. And this doesn’t slow you down too much: the default response is «yes, I do want to rename» so you can just hit the enter key at each prompt (because of the -z $run test.

Источник

Оцените статью
Adblock
detector