Вопрос по bash, shell – Как удалить префикс имени файла с помощью оболочки Posix

24

Как я могу удалить префикс имени файла в Bash, как в следующем примере:

<code>XY TD-11212239.pdf
</code>

получить

<code>11212239.pdf
</code>

т.е. удалитьXY TD-?

@ Shahbaz: Хм .. Но ОП говорит, чтоXY TD- «префикс имени файла», который он хочет удалить. Тогда «XY» не может быть командой оболочки. ArjunShankar
@hamid - Хотите переименовать файлы, удалив префикс? Вы хотите сделать это в оболочке, например, в bash или в программе (на каком языке?)? ArjunShankar
Linux - это ядро. Вы на самом деле имеете в виду [bash] или [sh] (или другую оболочку) вместо этого? ArjunShankar
Редактирование @ Shahbaz: хотя ОП, вероятно, означало «оболочку», на самом деле это можно сделать, например, написав программу на Си. Я имею в виду следующее: лучше позволить ОП уточнить, имел ли он в виду «оболочка». ArjunShankar
@ArjunShankar, я удалил оболочку из заголовка, но, кстати, он выполняет команду (XY file-nameЯ до сих пор считаю, что он хочет сделать это в оболочке. Shahbaz

Ваш Ответ

5   ответов
25

Вы сказалиPOSIX оболочки, которые будут включать BASH, Kornshell, Ash, Zsh и Dash. К счастью, все эти оболочки делаютpattern filtering на значения переменных.

Шаблоны - это то, что вы используете при указании файлов с такими вещами, как* в командной строке Unix / Linux:

$ ls *.sh  # Lists all files with a `.sh` suffix

Эти оболочки POSIX используют четыре разных шаблона фильтрации:

  • ${var#pattern} - Removes smallest string from the left side that matches the pattern.
  • ${var##pattern} - Removes the largest string from the left side that matches the pattern.
  • ${var%pattern} - Removes the smallest string from the right side that matches the pattern.
  • ${var%%pattern} - Removes the largest string from the right side that matches the pattern.

Вот несколько примеров:

foo="foo-bar-foobar"
echo ${foo#*-}   # echoes 'bar-foobar'  (Removes 'foo-' because that matches '*-')
echo ${foo##*-}  # echoes 'foobar' (Removes 'foo-bar-')
echo ${foo%-*}   # echoes 'foo-bar'
echo ${foo%%-*}  # echoes 'foo'

Вы действительно не объяснили, что вы хотите, и вы не включили ни одного примера кода, поэтому трудно придумать что-то, что будет делать то, что вы хотите. Однако, используя шаблонную фильтрацию, вы, вероятно, сможете точно определить, что вы хотите делать с именами файлов.

file_name="XY TD-11212239.pdf"
mv "$file_name" "${file_name#*-}" # Removes everything from up to the first dash
1
$ s='XY TD-11212239.pdf'
$ echo "${s#XY TD-}"
11212239.pdf

Если ваша цель - выполнить массовое переименование:

while IFS= read -r -d '' filename; do
  mv "$filename" "${filename#XY TD-}"
done < <(find . -type f -name 'XY TD-*' -print0)

Обратите внимание, что<() это расширение bash, отсутствующее в POSIX sh. Вы можете заменить его конвейером видаfind ... | while.

Так же,-print0 это расширение GNU, которого нет в POSIX find. POSIX find не предоставляет эквивалентного способа поиска файлов, который безопасен для имен, содержащих символы новой строки, что затрудняет его замену.

27

Вы дали очень мало информации, но, предполагая, что вы делаете это в bash, и у вас есть список файлов, префикс которых необходимо удалить, вы можете перенаправить этот список черезsed:

Например:

./generate_your_list_of_files | sed -e 's/^prefix//'

или если ваш список файлов разделен пробелами:

echo TD-file1 TD-file2.x.yt TD-file3-beep | sed -e 's/\<TD-//g'

Первый соответствует префиксу в начале строки и удаляет его. Второй соответствуетTD- (или любой другой префикс, который вы хотите заменить) только тогда, когда это происходит в начале слова и заменяет его во всех совпадениях во всех строках. этоcould опасно, хотя, например, файл, какTD-file\ that\ TD-contains\ space.txt становитсяfile\ that\ contains\ space.txt

Как примечание, не получайте ваш список файлов, используяls. Это ужасная ошибка, Если вам нужно получить список файлов для работы и ссылки на них более чем в одном месте, я предлагаю разместить их в массиве:

files=(*)

а затем работать с этим массивом.


Из-за популярных запросов (единственный комментарий ниже), вот как переименовать все файлы в каталоге, которые начинаются сXY TD- такой, что префикс удален (спасибо @tripleee):

for file in prefix*;
do
    mv "$file" "${file#XY TD-}"
done
@tripleee, это волшебство!
... и за оперативность и правильность,mv "$file" "${file#XY\ TD-}" с правильным цитированием и встроенным в оболочку механизмом замены.
@tripleee, спасибо, что сообщили мне об этом. На самом деле, я только недавно изучал скриптовый язык bash. Я обновил свой ответ.
@ArjunShankar, см. Мое редактирование.
Также возможно, что OP хочет «переименовать»; оригинальные файлы. Вопросы действительно слишком расплывчаты, чтобы на них было достаточно ответов.
2

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

fn="XY TD-11212239.pdf"

Затем замена подстроки:

fn_new=${fn//*TD-/}

Также буду делать что хочешь.

Это спасло мое здравомыслие сегодня. Благодарю.
4

Вы также можете использоватьrename инструмент

Установите его с домашним пивом

brew install rename

Затем выполните указанную ниже команду из каталога, чтобы удалить префикс & quot; из всех файлов

rename -d prefix- *

Хороший мощныйperl инструмент!

Похожие вопросы