2010-08-12 3 views
2

У меня есть большое количество файлов изображений, которые мне нужно переименовать из строки comand. Я считаю, что лучший способ сделать это - использовать awk (пожалуйста, исправьте, если это неверно).Пакетное переименование файлов с использованием UNIX - следует ли использовать awk?

имена файлов, как в следующем

1038282829128738912-1.jpg 

Каждый файл изображения начинается с «103», и я хочу, чтобы заменить эту часть имени файла с «201003» - оставляя нетронутыми остальные ... например.

2010038282829128738912-1.jpg 

Изображения находятся в нескольких папках под одной основной папке (изображения) - но это было бы удобно для всех изображений, которые будут скопированы в одну папку (images_renamed)

Я не знаю, где начните с этого - и я googled для использования awk, но могу найти только примеры переименования текста внутри файлов.

Любая помощь приветствуется. Благодаря/

+0

Perl-скрипт 'rename' делает эту работу сподручно. Действительно, одним из мотивов написания Perl была ограниченная поддержка awk для многих файлов. 'rename' должен уже быть частью дистрибутивов на основе debian или http://search.cpan.org/~rmbarker/File-Rename-0.05/ – msw

+0

Спасибо за все ваши ответы - я собираюсь немного почитать и попробовать из них. Я вернусь позже и отвечу на вопрос: я уверен, что здесь должны быть правильные ответы :-) Еще раз спасибо. – calumbrodie

+0

здесь: http: //theunixshell.blogspot.com/2013/01/bulk-renaming-of-files-in-unix.html – Vijay

ответ

6

Если у вас есть rename команду на вашем UNIX, вы должны быть в состоянии использовать что-то вроде:

mkdir images_renamed 
cd images_renamed 
cp ../103*.jpg . 
rename 103 201003 *.jpg 

rename FROM TO FILE будет переименовать все файлы, указанные FILE, изменение первого вхождения FROM в TO.

Если это не доступно, вы можете использовать что-то вроде:

mkdir images_renamed 
for fspec in 103*.jpg ; do 
    cp ${fspec} images_renamed/201003${fspec:3} 
done 

Чтобы сделать это рекурсивно, я бы поставил его в сценарий с find:

#!/usr/bin/bash 

rm -rf images_renamed 
ls -lR images 
echo 

cd images 
find . -name '*.jpg' | while read -r; do 
    mkdir -p "../images_renamed/$(dirname "$REPLY")" 
    echo 'Copying from' [$REPLY] 
    echo '   to' [../images_renamed/$REPLY] and renaming. 
    echo 
    cp "$REPLY" "../images_renamed/$REPLY" 
    cd "$(dirname "../images_renamed/$REPLY")" 
    rename 103 201003 "$(basename "$REPLY")" 
    cd - >/dev/null 
done 

cd .. 
ls -lR images_renamed 

Только средний немного, что требуется, остальные для тестирования. Вывод ниже показывает, как он работает, копируя все файлы в новую структуру каталогов и переименовывая соответствующие файлы.

images: 
total 0 
drwxr-xr-x+ 1 pax None 0 2010-08-12 20:55 dir1 
drwxr-xr-x+ 1 pax None 0 2010-08-12 20:55 dir2 
drwxr-xr-x+ 1 pax None 0 2010-08-12 20:56 dir3 

images/dir1: 
total 0 
-rw-r--r-- 1 pax None 0 2010-08-12 20:55 102xxx.jpg 
-rw-r--r-- 1 pax None 0 2010-08-12 20:55 103xxx.jpg 

images/dir2: 
total 0 
-rw-r--r-- 1 pax None 0 2010-08-12 20:55 103yyy.jpg 

images/dir3: 
total 0 
drwxr-xr-x+ 1 pax None 0 2010-08-12 20:55 dir 4 

images/dir3/dir 4: 
total 0 
-rw-r--r-- 1 pax None 0 2010-08-12 20:55 103zzz.jpg 

Copying from [./dir1/102xxx.jpg] 
      to [../images_renamed/./dir1/102xxx.jpg] and renaming. 

Copying from [./dir1/103xxx.jpg] 
      to [../images_renamed/./dir1/103xxx.jpg] and renaming. 

Copying from [./dir2/103yyy.jpg] 
      to [../images_renamed/./dir2/103yyy.jpg] and renaming. 

Copying from [./dir3/dir 4/103zzz.jpg] 
      to [../images_renamed/./dir3/dir 4/103zzz.jpg] and renaming. 

images_renamed: 
total 0 
drwxr-xr-x+ 1 pax None 0 2010-08-12 21:19 dir1 
drwxr-xr-x+ 1 pax None 0 2010-08-12 21:19 dir2 
drwxr-xr-x+ 1 pax None 0 2010-08-12 21:19 dir3 

images_renamed/dir1: 
total 0 
-rw-r--r-- 1 pax None 0 2010-08-12 21:19 102xxx.jpg 
-rw-r--r-- 1 pax None 0 2010-08-12 21:19 201003xxx.jpg 

images_renamed/dir2: 
total 0 
-rw-r--r-- 1 pax None 0 2010-08-12 21:19 201003yyy.jpg 

images_renamed/dir3: 
total 0 
drwxr-xr-x+ 1 pax None 0 2010-08-12 21:19 dir 4 

images_renamed/dir3/dir 4: 
total 0 
-rw-r--r-- 1 pax None 0 2010-08-12 21:19 201003zzz.jpg 

Чтобы распрямить иерархию файлов, вы можете использовать что-то вроде:

#!/usr/bin/bash 

rm -rf images_renamed 
ls -lR images 
echo 

cd images 
mkdir -p ../images_renamed 
find . -name '*.jpg' | while read -r; do 
    newfile="$(basename "$REPLY")" 
    echo 'Copying from' [$REPLY] 
    echo '   to' [../images_renamed/$newfile] and renaming. 
    echo 
    cp "$REPLY" "../images_renamed/$newfile" 
    cd ../images_renamed 
    rename 103 201003 "$newfile" 
    cd - >/dev/null 
done 

, который выводит:

cd .. 
ls -lR images_renamed 
images: 
total 0 
drwxr-xr-x+ 1 allan None 0 2010-08-12 20:55 dir1 
drwxr-xr-x+ 1 allan None 0 2010-08-12 20:55 dir2 
drwxr-xr-x+ 1 allan None 0 2010-08-12 20:56 dir3 

images/dir1: 
total 0 
-rw-r--r-- 1 allan None 0 2010-08-12 20:55 102xxx.jpg 
-rw-r--r-- 1 allan None 0 2010-08-12 20:55 103xxx.jpg 

images/dir2: 
total 0 
-rw-r--r-- 1 allan None 0 2010-08-12 20:55 103yyy.jpg 

images/dir3: 
total 0 
drwxr-xr-x+ 1 allan None 0 2010-08-12 20:55 dir 4 

images/dir3/dir 4: 
total 0 
-rw-r--r-- 1 allan None 0 2010-08-12 20:55 103zzz.jpg 

Copying from [./dir1/102xxx.jpg] 
      to [../images_renamed/102xxx.jpg] and renaming. 

Copying from [./dir1/103xxx.jpg] 
      to [../images_renamed/103xxx.jpg] and renaming. 

Copying from [./dir2/103yyy.jpg] 
      to [../images_renamed/103yyy.jpg] and renaming. 

Copying from [./dir3/dir 4/103zzz.jpg] 
      to [../images_renamed/103zzz.jpg] and renaming. 

images_renamed: 
total 0 
-rw-r--r-- 1 allan None 0 2010-08-12 22:41 102xxx.jpg 
-rw-r--r-- 1 allan None 0 2010-08-12 22:41 201003xxx.jpg 
-rw-r--r-- 1 allan None 0 2010-08-12 22:41 201003yyy.jpg 
-rw-r--r-- 1 allan None 0 2010-08-12 22:41 201003zzz.jpg 

но вы должны иметь в виду, что FileName столкновения (одно и то же имя файла в разных каталогах) перезаписывают друг друга.

+0

Рекурсивно ли это работает? – scy

+0

Нет, вам нужно найти обертку вокруг нее. Обновлен, чтобы показать один из способов сделать это. – paxdiablo

+0

Спасибо за ваш ответ. Единственное, что я хотел бы изменить, - это место назначения. Вместо сохранения структуры каталогов, в которой были скопированы файлы, я хочу, чтобы все изображения были скопированы в папку «images_renamed». Я попытался изменить сценарий, который вы предоставили, но не смог. Я не могу найти связь между $ REPLY и dirname, basename и т. Д. Я могу сказать, что $ REPLY - это полный путь и имя файла, которое соответствует команде find, но я могу извлечь только имя файла из этой информации для использования на этапе переименования (т.е. используя только имя файла, а не каталог) – calumbrodie

-1

не проверял, но что-то подобное может работать в Баш:

for i in `ls 103*.jpg`; do cp $i newdir/201003${i:3}; done 
+0

Это не работает с подкаталогами. – scy

+0

бесполезное использование ls – ghostdog74

0

В ZSH вы можете сделать это (вероятно, работает в Bash тоже не уверен в этом):

for f in **/103*.jpg; mv $f some_other_directory/201003${${f:t}#103} 

Возможно, я также могу заинтересовать вас в инструменте, который я написал: http://github.com/jkramer/virn Он позволяет вам массово переименовывать файлы с помощью Vim, включая все функции Vims, такие как регулярное выражение и т. Д.(На самом деле вы можете использовать любой другой $ EDITOR).

0

Нечто подобное могло бы помочь:

cd images 
find . -name '*.jpg' | while read -r img; do 
    mkdir -p "../images_renamed/$(dirname "$img")" 
    cp -v "$img" "../images_renamed/$(echo "$img" | sed -e 's/^103/201003/')" 
done 

Примечание: Не тестировалось. Однако не следует удалять вещи.

+0

Вы действительно хотите создать каталог для каждого файла? –

+0

Это не то, что я делаю. Я беру исходное имя файла (включая каталог) и создаю этот каталог и возможные каталоги над ним. Возможно, вы захотите снова прочитать эту строку. – scy

0

должно работать:

ls -d images* 
images/   images_renamed/ 


for i in `find images -type f` 
do 
    cp $i images_renamed/$(basename $i | sed s/^103/201003/) 
done 
+0

Не работает, если имена файлов содержат пробелы. Используйте 'find | в то время как read' и quote, содержащие имена файлов. –

+0

согласился, но не чувствовал необходимости делать это на основе соглашения об именах файлов OP. – dogbane

0
find /path -type f -name "10*jpg" | sed 's/.*/mv &/' | sed 's/mv \(.*\/\)\(.[^/]*\)/& \120\2/' | sh 
+0

Иисус. Это не нормально. Но это может сработать. – scy

Смежные вопросы