- unixforum.org
- Re: Переименование части названия файла
- Re: Переименование части названия файла
- Re: Переименование части названия файла
- Re: Переименование части названия файла
- Re: Переименование части названия файла
- Re: Переименование части названия файла
- Re: Переименование части названия файла
- Re: Переименование части названия файла
- Re: Переименование части названия файла
- Re: Переименование части названия файла
- Re: Переименование части названия файла
- Re: Переименование части названия файла
- Re: Переименование части названия файла
- Re: Переименование части названия файла
- Re: Переименование части названия файла
- Re: Переименование части названия файла
- Re: Переименование части названия файла
- Renaming part of a filename [duplicate]
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
Вот блин, как неудобно. В 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
предложите работающий вариант)
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к файлов. Хех.. и количество вызовов команды-таки остается решающим.
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» «$
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.