Bash извлечение файла basename из длинного пути

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

files="/very/long/path/to/various/files/*.file"

Поэтому я мог бы использовать его так.

prompt> program -files $files -names $namelist

Если glob дает мне:

/very/long/path/to/various/files/AA.file /very/long/path/to/various/files/BB.file /very/long/path/to/various/files/CC.file /very/long/path/to/various/files/DD.file /very/long/path/to/various/files/ZZ.file

Я хотел бы получить список AA BB CC DD ZZ, чтобы прокормить мою программу без длинного пути и расширения файла. Однако я не знаю, как начать там! Любой намек высоко ценится!

Ответ 1

Лучше использовать массив для хранения имен файлов. Строковая переменная не будет обрабатывать имена файлов, которые содержат пробелы.

Кроме того, вам не нужно использовать команду basename. Вместо этого используйте bash встроенную обработку строк.

Попробуйте следующее:

files=( /very/long/path/to/various/files/*.file )
for file in "${files[@]}"
do
  filename="${file##*/}"
  filenameWithoutExtension="${filename%.*}"
  echo "$filenameWithoutExtension"
done

Ответ 2

Решение с basename для вашего вопроса

for file in $files
do
  file_name=$(basename $file)
  file_name_witout_ext=${file_name%.file}
done

изменить (общий способ извлечения имени файла без (одного) расширения)

for file in $files
do
  file_name=$(basename $file)
  file_name_witout_ext=${file_name%.*}
done

Еще одна вещь, которая может случиться, - иметь имя файла, например, archive.tar.gz. В этом случае у вас будет два (или несколько расширений). Затем вы можете использовать более greddy operator

for file in $files
do
  file_name=$(basename $file)
  file_name_witout_ext=${file_name%%.*}
done

Ответ 3

Это проще:

files=(/very/long/path/to/various/files/*.file)
names=("${files[@]##*/}") names=("${names[@]%.*}")
progname -files "${files[@]}" -names "${names[@]}"

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

progname -files "${files[*]}" -names "${names[*]}"