2

У меня есть несколько тысяч файлов в форме:

[8-значный номер] _ [номер, который я хочу] _S60491_I129111.dcm.

Я хочу удалить все, кроме нужного мне номера, и использовать его в качестве имени. В Ruby я могу получить это значение с помощью регулярного выражения /^.*_(\d+)_S60491_I12911.dcm/ , но у меня возникают проблемы при попытке преобразовать его в выражение sed которое позволяет мне заменить полное имя файла на просто это число между подчеркиваниями.

Есть ли способ использовать sed или другие базовые команды Bash, чтобы делать то, что я хочу? Если это помогает, то номер, который я хочу, - это просто счетчик (т.е. он работает от 1 до 2100), и префикс 8-значный номер приводит к тому, что файлы перечислены в правильном порядке (то есть от файла 1 до файла 2100), так что я, может быть, обдумываю вещи.

4 ответа4

2

Существует инструмент, обычно называемый переименованием или prename установленный в большинстве систем. В моих системах Debian/Ubuntu это входит в состав Perl. Это позволяет вам использовать регулярные выражения в стиле Perl для манипулирования именами файлов, как вам нравится.

Ваша команда, вероятно, будет выглядеть так. Я советую вам пропустить опцию --no-act и проверить вывод, прежде чем вы действительно внесете какие-либо изменения.

prename 's/^.*_(\d+)_S60491_I12911.dcm/$1/' *
1

Это работает для меня: for a in * ; do mv "$a" $(echo "$a" | cut -d'_' -f 2) ; done

toad:/home/hennes/work/foo>ls -l
total 0
-rw-------  1   users  0 Jan 23 22:19 12345678_023454_S60491_I129111.dcm
-rw-------  1   users  0 Jan 23 22:19 12345678_123454_S60491_I129111.dcm
-rw-------  1   users  0 Jan 23 22:19 12345678_123456_S60491_I129111.dcm

toad:/home/hennes/work/foo>for a in * ; do mv $a $(echo $a | cut -d'_' -f 2) ; done

toad:/home/hennes/work/foo>ls -l
total 0
-rw-------  1   users  0 Jan 23 22:23 023454
-rw-------  1   users  0 Jan 23 22:23 123454
-rw-------  1   users  0 Jan 23 22:23 123456

for a in * выбирает все файлы. Если есть еще файлы, вместо них можно использовать * .dcm.

mv (move) меняет имя файла

от $ a (имя файла выбирается для)

для field2 имени, с _ используется разделитель полей.

Обратите внимание, что этот скрипт будет перемещать файлы, поэтому старые имена файлов будут потеряны. Вы можете использовать «cp» вместо «mv», чтобы сделать копию.

Если вы хотите сохранить расширение, добавьте его после -f 2).
Например, for a in * ; do cp $a $(echo $a | cut -d'_' -f 2).dcm ; done

1

Так как мы знаем формат имен и ни один из них не содержит пробелов:

for a in * ; do
   mv $a $(echo $a | sed 's/[^_]*_//;s/_S60491_I129111.dcm//')
done
0

Есть много способов сделать это. Но так как вы попросили sed , это будет делать:

ls dcm | sed 's/^([0-9] {8} _([0-9])_S60491_I129111.dcm)/mv \1 \2 /g' | удар

Первый бит шаблона выбирает 8-значные числа, затем вы ищите любые цифры (так как вы не упомянули, каков был размер второго числа), а затем ваш трейлинг-последовательность. \1 и \2 ссылаются на содержимое внешних и внутренних экранированных скобок \(...\) . В этом случае вы можете заменить bash на любую оболочку.

Расширения GNU для sed позволят вам также:

ls * dcm | sed 's/^([0-9] {8} _([0-9]+)_ S60491_I129111.dcm)/mv \1 \2 /g' | удар

где + соответствует одному или нескольким, где * соответствует нулю или нескольким, что вызывает проблемы для 12345678__S60491_I129111.dcm .

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .