Как извлечь путь к директории из пути к файлу?
В 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
Как разделить большой текстовый файл на меньшие файлы с равным количеством строк?
Автоматический вход в Docker через Bash-скрипт