Как извлечь путь к директории из пути к файлу?
В Bash, у меня есть переменная VAR="/home/me/mydir/file.c"
, и мне нужно извлечь из неё путь "/home/me/mydir"
. Как это можно сделать?
5 ответ(ов)
Вы можете использовать параметры подстановки в оболочке Bash для извлечения компонентов пути файла без необходимости использования дополнительных утилит, таких как basename
и dirname
.
В приведенном вами примере:
Вы задаете переменную
VAR
со значением/home/me/mydir/file.c
.Затем с помощью
${VAR%/*}
вы извлекаете директорию, которая находится до последнего слэш-символа в пути. В результате этой операции вы получите/home/me/mydir
, и это значение присваивается переменнойDIR
.Для извлечения имени файла, которое является частью пути, вы используете
${VAR##*/}
. Это выражение удаляет все символы до последнего слэша (включительно), оставляя только имя файла, то естьfile.c
.
Таким образом, вы получаете рабочий способ извлечения директории и имени файла, не полагаясь на утилиты basename
и dirname
, только с помощью встроенных возможностей оболочки Bash.
Если у вас есть только имя файла или относительный путь, то dirname
сам по себе не поможет решить задачу. В моем случае ответом стал readlink
.
fname='txtfile'
echo $(dirname "$fname") # вывод: .
echo $(readlink -f "$fname") # вывод: /home/me/work/txtfile
Вы можете объединить оба этих вызова, чтобы получить только директорию:
echo $(dirname $(readlink -f "$fname")) # вывод: /home/me/work
Если вам нужно обработать целевые файлы как символические ссылки, сначала вы можете проверить, является ли файл символической ссылкой, и получить оригинальный файл. В приведённом ниже условии if
может быть полезно следующее:
if [ -h $file ]
then
base=$(dirname $(readlink $file))
else
base=$(dirname $file)
fi
Этот код сначала проверяет, является ли файл символической ссылкой с помощью -h
. Если это так, он использует команду readlink
для получения пути к оригинальному файлу и извлекает его директорию с помощью dirname
. Если файл не является символической ссылкой, просто извлекается директория исходного файла.
Команда HERE=$(cd $(dirname $BASH_SOURCE) && pwd)
используется для получения полного пути к каталогу, в котором находится скрипт.
Давайте разберем её по частям:
$(dirname $BASH_SOURCE)
— эта часть получает путь к каталогу, где расположен текущий исполняемый скрипт. Переменная$BASH_SOURCE
содержит путь к скрипту, и командаdirname
извлекает из него директорию.cd $(dirname $BASH_SOURCE)
— здесь мы переходим в полученный каталог. Это позволяет нам изменить рабочую директорию на ту, где находится скрипт.pwd
— эта команда выводит текущий рабочий каталог в терминале.
Таким образом, вся команда HERE=$(cd $(dirname $BASH_SOURCE) && pwd)
сначала перемещает нас в директорию скрипта, а затем сохраняет полный путь к этой директории в переменную HERE
.
При этом, такая конструкция позволяет избежать ошибок, связанных с относительными путями, что полезно при работе со скриптами, которые могут быть запущены из разных мест.
Вы можете использовать команду dirname
для извлечения каталога из пути файла, и ваш подход с использованием xargs
тоже работает. Вот пример, который я нашел:
$ VAR=/home/me/mydir/file.c
$ DIR=`echo $VAR | xargs dirname`
$ echo $DIR
/home/me/mydir
Мне понравился ваш способ, так как его легко расширить для получения родительских каталогов. Например, если вам нужно подняться на два уровня вверх по дереву каталогов, вы можете сделать следующее:
$ DIR=`echo $VAR | xargs dirname | xargs dirname | xargs dirname`
$ echo $DIR
/home
Этот код успешно извлекает нужный путь, поднимаясь вверх по дереву каталогов. Однако можно упростить код, используя dirname
несколько раз в одном выражении, без использования xargs
. Например:
$ DIR=$(dirname $(dirname $(dirname $VAR)))
$ echo $DIR
/home
Такой подход делает код более читаемым и понятным.
Как изменить цвет вывода echo в Linux
Как работает "cat << EOF" в bash?
Передача параметров в функцию Bash
Расширение переменных внутри одинарных кавычек в команде Bash
Как разделить большой текстовый файл на меньшие файлы с равным количеством строк?