Получить только имя файла из пути в сценарии Bash
Как получить только имя файла без расширения и без пути?
Следующее не дает мне расширения, но у меня все еще есть путь:
source_file_filename_no_ext=${source_file%.*}
- переадресовать COPY stdout для записи файла из самого скрипта bash
- Каково точное значение IFS = $ '\ n'?
- Случайное число из диапазона в сценарии Bash
- Преобразование даты времени в эпоху в Bash
- Сценарии Bash, множественные условия во время цикла
- Сценарий оболочки для захвата идентификатора процесса и его уничтожения, если существует
- Можно ли отображать распечатанный вывод через redirect оболочки?
- Как Ctrl-C завершает дочерний процесс?
- Как команда сортировки UNIX может сортировать очень большой файл?
- Дата даты YYYY-MM-DD в сценарии оболочки
- Преобразование абсолютного пути в относительный путь с учетом текущего каталога с использованием Bash
- Как разбить строку на разделителе в Bash?
- Почему равный оператор не работает, если он не окружен пространством?
Большинство UNIX-подобных операционных систем имеют исполняемый файл basename
для очень сходной цели (и dirname
для пути):
pax> a=/tmp/file.txt pax> b=$(basename $a) pax> echo $b file.txt
Это, к сожалению, просто дает вам имя файла, включая расширение, поэтому вам также нужно найти способ снять это.
Поэтому, учитывая, что вы все равно должны это сделать, вы также можете найти метод, который может удалить путь и расширение.
Один из способов сделать это (и это bash
единственное решение, не требующее других исполняемых файлов):
pax> a=/tmp/xx/file.tar.gz pax> xpath=${a%/*} pax> xbase=${a##*/} pax> xfext=${xbase##*.} pax> xpref=${xbase%.*} pax> echo;echo path=${xpath};echo pref=${xpref};echo ext=${xfext} path=/tmp/xx pref=file.tar ext=gz
Этот маленький fragment устанавливает xpath
(путь к файлу), xpref
(префикс файла, то, что вы специально запрашивали) и xfext
(расширение файла).
basename
и dirname
решения более удобны. Это альтернативные команды:
FILE_PATH="/opt/datastores/sda2/test.old.img" echo "$FILE_PATH" | sed "s/.*\///"
Это возвращает test.old.img
как basename
.
Это соленое имя файла без расширения:
echo "$FILE_PATH" | sed -r "s/.+\/(.+)\..+/\1/"
Он возвращает test.old
.
И следующая инструкция дает полный путь, как команда dirname
.
echo "$FILE_PATH" | sed -r "s/(.+)\/.+/\1/"
Он возвращает /opt/datastores/sda2
Вот простой способ получить имя файла из пути:
echo "$PATH" | rev | cut -d"/" -f1 | rev
Чтобы удалить расширение, которое вы можете использовать, если имя файла имеет только одну точку (добавочную точку):
cut -d"." -f1
$ source_file_filename_no_ext=${source_file%.*} $ echo ${source_file_filename_no_ext##*/}
$ file=${$(basename $file_path)%.*}
Несколько альтернативных вариантов, потому что регулярные выражения (regi?) Являются удивительными!
Вот простое регулярное выражение для выполнения задания:
regex="[^/]*$"
Пример (grep):
FP="/hello/world/my/file/path/hello_my_filename.log" echo $FP | grep -oP "$regex" #Or using standard input grep -oP "$regex" <<< $FP
Пример (awk):
echo $FP | awk '{match($1, "$regex",a)}END{print a[0]} #Or using stardard input awk '{match($1, "$regex",a)}END{print a[0]} <<< $FP
Если вам нужно более сложное регулярное выражение: например, ваш путь завернут в строку.
StrFP="my string is awesome file: /hello/world/my/file/path/hello_my_filename.log sweet path bro." #this regex matches a string not containing / and ends with a period #then at least one word character #so its useful if you have an extension regex="[^/]*\.\w{1,}" #usage grep -oP "$regex" <<< $StrFP #alternatively you can get a little more complicated and use lookarounds #this regex matches a part of a string that starts with / that does not contain a / ##then uses the lazy operator ? to match any character at any amount (as little as possible hence the lazy) ##that is followed by a space ##this allows use to match just a file name in a string with a file path if it has an exntension or not ##also if the path doesnt have file it will match the last directory in the file path ##however this will break if the file path has a space in it. regex="(?<=/)[^/]*?(?=\s)" #to fix the above problem you can use sed to remove spaces from the file path only ## as a side note unfortunately sed has limited regex capibility and it must be written out in long hand. NewStrFP=$(echo $StrFP | sed 's:\(/[az]*\)\( \)\([az]*/\):\1\3:g') grep -oP "$regex" <<< $NewStrFP
Общее решение с регулярными выражениями:
Эта функция может предоставить вам имя файла с расширением или без расширения пути к файлу linux, даже если имя файла имеет несколько «.» S в нем. Он также может обрабатывать пробелы в пути к файлу, и если путь к файлу встроен или завернут в строку.
#you may notice that the sed replace has gotten really crazy looking #I just added all of the allowed characters in a linux file path function Get-FileName(){ local FileString="$1" local NoExtension="$2" local FileString=$(echo $FileString | sed 's:\(/[a-zA-Z0-9\<\>\|\\\:\)\(\&\;\,\?\*]*\)\( \)\([a-zA-Z0-9\<\>\|\\\:\)\(\&\;\,\?\*]*/\):\1\3:g') local regex="(?<=/)[^/]*?(?=\s)" local FileName=$(echo $FileString | grep -oP "$regex") if [[ "$NoExtension" != "" ]]; then sed 's:\.[^\.]*$::g' <<< $FileName else echo "$FileName" fi } ## call the function with extension Get-FileName "my string is awesome file: /hel lo/world/my/file test/path/hello_my_filename.log sweet path bro." ##call function without extension Get-FileName "my string is awesome file: /hel lo/world/my/file test/path/hello_my_filename.log sweet path bro." "1"
Если вам нужно возиться с окном, вы можете начать с этого:
[^\\]*$