Список расширений имен файлов в bash-скрипте в одну строку - PullRequest
0 голосов
/ 25 июня 2018

В настоящее время у меня есть следующая строка кода:

ls /some/dir/prefix* | sed -e 's/prefix.//' | tr '\n' ' '

Что позволяет добиться того, чего я хочу:

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

Например:

/some/dir/prefix.hello
/some/dir/prefix.world

Должен стать

hello world

Но я чувствую, что есть более хороший способ сделать это.Есть ли лучший способ сделать это в одну строку?

Ответы [ 4 ]

0 голосов
/ 26 июня 2018

Вот очень простая однострочная Awk для достижения этой цели:

awk -F. '{$0=FILENAME; printf $NF" "; nextfile}' /some/dir/prefix*

По сути, это делает следующее:

  • -F.: установите разделитель поля FS на .. Таким образом, $NF представляет расширение.
  • $0=FILENAME: игнорировать текущую запись и установить ее на FILENAME, обработать все таким образом.
  • print $NF; nextfile: распечатать расширение и перейти к следующему файлу.

Проблема в том, что файл все еще читает запись текущего файла. Если этот файл пуст, это не удастся.

Чтобы это работало с пустыми файлами, вы можете использовать расширение gawk BEGINFILE

awk -F. 'BEGINFILE{$0=FILENAME; printf $NF" "; nextfile}' /some/dir/prefix*

Или вы можете перебрать все аргументы:

awk -F. 'BEGIN{for(i in ARGV){$0=ARGV[i]; printf $NF" "};exit}' /some/dir/prefix*
0 голосов
/ 25 июня 2018

Вот две строки, использующие только встроенные модули, которые делают это:

fnames=(some/dir/prefix*)
echo "${fnames[@]##*.}"

А вот как это работает:

  • fnames=(some/dir/prefix*) создает массив со всеми файлами, начинающимися с prefix, и избегает всех проблем, возникающих при разборе ls
  • echo "${fnames[@]##*.}" представляет собой комбинацию двух расширений параметров: ${fnames[@]} печатает все элементы массива, а часть ##*. удаляет самое длинное совпадение из всего, что заканчивается . из каждого элемента массива, оставляя только расширение

Если вы одержимы однострочностью, просто объедините две команды с помощью &&.

0 голосов
/ 25 июня 2018

Передача ls вывода во внешние программы не рекомендуется, вам может помочь следующее решение bash.

for file in prefix*; do echo ${file##*.}; done

Теперь добавляется не только один вариант решения.

for file in prefix*
do
   echo ${file##*.}
done
0 голосов
/ 25 июня 2018

Один подход с awk:

ls /some/dir/prefix* | awk -F"." '{printf "%s ", $2} END {print ""}'

Это может квалифицироваться как «более приятное», потому что есть только одна команда, через которую передается вывод?!

...