цитаты внутри важны, иначе вы потеряете все свои данные
катамфетамин
11
и вариант, который я использую, чтобы получить родителя текущего рабочего каталога: parentdir=$(dirname `pwd`)
TheGrimmScientist
3
Обратите внимание, этот метод небезопасен для «некрасивых» имен. Имя типа «-rm -rf» нарушит желаемое поведение. Наверное "." будет тоже. Я не знаю, является ли это лучшим способом, но я создал отдельный вопрос, «сфокусированный на правильности»: stackoverflow.com/questions/40700119/…
VasiliNovikov
4
@Christopher Shroba Да, я опустил кавычки, а затем мой HDD оказался частично стертым. Я точно не помню, что произошло: по-видимому, каталог без пробелов заставил его стереть родительский каталог вместо целевого - мой скрипт просто стер папку / home / xxx /.
катамфетамин
3
о хорошо, так что в команде нет ничего, что могло бы привести к потере любых данных, если вы уже не выполняете команду удаления, верно? Это был просто вопрос пути, который вы пытались удалить, разделив пробел на символ пробела и удалив гораздо больше, чем ожидалось?
Кристофер Шроба
18
... но то, что "видно здесь ", сломано. Вот исправление:
Просто используйте echo $(cd ../ && pwd)при работе в каталоге, родительский каталог которого вы хотите узнать. Эта цепь также имеет дополнительное преимущество, заключающееся в том, что она не имеет конечных слешей.
Использование evalНЕЛЬЗЯ, если есть возможность проанализировать пользовательский ввод, который может привести вас туда, куда вы не ожидаете, или создать что-то плохое для вашей системы. Вы можете использовать pushd $dir 2>&1 >/dev/null && pwd && popd 2>&1 >/dev/nullвместо eval?
dragon788
2
Вам не нужно evalвообще: просто делай parentdir=$(cd -- "$dir" && pwd). Поскольку cdон запускается в подоболочке, вам не нужно cdвозвращаться туда, где мы были. Это --здесь в случае, если расширение $dirначинается с дефиса. Это &&просто для того, чтобы не parentdirиметь непустого контента, когда cdне получилось.
gniourf_gniourf
8
Мотивация для другого ответа
Мне нравится очень короткий, понятный, гарантированный код. Бонусный балл, если не запускается внешняя программа, поскольку в тот день, когда вам нужно обработать огромное количество записей, это будет заметно быстрее.
Принцип
Не уверен насчет того, какие гарантии у вас есть и чего вы хотите, так что предлагайте в любом случае.
Если у вас есть гарантии, вы можете сделать это с очень коротким кодом. Идея состоит в том, чтобы использовать функцию подстановки текста в bash, чтобы вырезать последнюю косую черту и все последующее.
Ответ от простых до более сложных случаев исходного вопроса.
Если путь гарантированно заканчивается без косой черты (внутри и снаружи)
Если входной путь может заканчиваться нулем или одной косой чертой (не более), и вы хотите, чтобы выходной путь заканчивался без косой черты
for P in \
/home/smith/Desktop/Test \
/home/smith/Desktop/Test/do
P_ENDNOSLASH="${P%/}"; echo "${P_ENDNOSLASH%/*}"done/home/smith/Desktop/home/smith/Desktop
Если входной путь может иметь много посторонних слешей и вы хотите, чтобы выходной путь заканчивался без слеша
for P in \
/home/smith/Desktop/Test \
/home/smith/Desktop/Test/ \
/home/smith///Desktop////Test//do
P_NODUPSLASH="${P//\/*(\/)/\/}"
P_ENDNOSLASH="${P_NODUPSLASH%%/}"
echo "${P_ENDNOSLASH%/*}";done/home/smith/Desktop/home/smith/Desktop/home/smith/Desktop
Фантастический ответ. Поскольку кажется, что он искал способ сделать это из сценария (найдите текущий каталог сценария и его родительский элемент и сделайте что-нибудь относительно места расположения сценария), это отличный ответ, и вы можете иметь еще больший контроль над тем, ввод имеет косую черту или нет, используя расширение параметра, по ${BASH_SOURCE[0]}которому будет полный путь к сценарию, если он не был получен через sourceили ..
dragon788
7
Если /home/smith/Desktop/Test/../это то, что вы хотите:
извините, я имею в виду, как скрипт bash, у меня есть переменная с путем к файлу
YTKColumba
Запуск этого кода дает мне ошибку bash: dirname 'Test': syntax error: invalid arithmetic operator (error token is "'Test'"). Связанный код тоже неверен.
Майкл Хоффман
попробуйте просто запустить dirname Testиз каталога Testв.
Джон Эгеланн
1
В зависимости от того, нужны ли вам абсолютные пути, вы можете сделать дополнительный шаг:
local lookFor_ parent_ switch_ i_
lookFor_="$1"#if it is not a file, we need the grand parent[-f "$lookFor_"]|| switch_="/.."#length of search string
i_="${#lookFor_}"#remove string one by one until it make sens for the systemwhile["$i_"-ge 0]&&[!-d "${lookFor_:0:$i_}"];do
let i_--done#get real path
parent_="$(realpath "${lookFor_:0:$i_}$switch_")"#done
echo "
lookFor_: $1
{lookFor_:0:$i_}: ${lookFor_:0:$i_}
realpath {lookFor_:0:$i_}: $(realpath ${lookFor_:0:$i_})
parent_: $parent_
"
если по какой - либо причине вы заинтересованы в навигации вверх определенное количество каталогов , которые вы могли бы также сделать: nth_path=$(cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && cd ../../../ && pwd). Это дало бы 3 родительских справочника
..
', но, возможно, это не совсем то, что вы имели в виду.Ответы:
Работает, если есть и косая черта.
источник
parentdir=$(dirname `pwd`)
... но то, что "видно здесь ", сломано. Вот исправление:
источник
Просто используйте
echo $(cd ../ && pwd)
при работе в каталоге, родительский каталог которого вы хотите узнать. Эта цепь также имеет дополнительное преимущество, заключающееся в том, что она не имеет конечных слешей.источник
echo
здесь.Понятно, что родительский каталог задается простым добавлением имени файла точка-точка:
Но вы должны хотеть разрешенный путь (абсолютный путь без каких-либо компонентов пути точка-точка):
Проблема с основными ответами, которые используют
dirname
, заключается в том, что они не работают, когда вы вводите путь с точечными точками:Это более мощный :
Вы можете кормить его
/home/smith/Desktop/Test/..
, но и более сложные пути, такие как:РЕДАКТИРОВАТЬ: Если это не работает, проверьте, что ваш
cd
не был изменен, как это часто бывает,источник
eval
НЕЛЬЗЯ, если есть возможность проанализировать пользовательский ввод, который может привести вас туда, куда вы не ожидаете, или создать что-то плохое для вашей системы. Вы можете использоватьpushd $dir 2>&1 >/dev/null && pwd && popd 2>&1 >/dev/null
вместоeval
?eval
вообще: просто делайparentdir=$(cd -- "$dir" && pwd)
. Посколькуcd
он запускается в подоболочке, вам не нужноcd
возвращаться туда, где мы были. Это--
здесь в случае, если расширение$dir
начинается с дефиса. Это&&
просто для того, чтобы неparentdir
иметь непустого контента, когдаcd
не получилось.Мотивация для другого ответа
Мне нравится очень короткий, понятный, гарантированный код. Бонусный балл, если не запускается внешняя программа, поскольку в тот день, когда вам нужно обработать огромное количество записей, это будет заметно быстрее.
Принцип
Не уверен насчет того, какие гарантии у вас есть и чего вы хотите, так что предлагайте в любом случае.
Если у вас есть гарантии, вы можете сделать это с очень коротким кодом. Идея состоит в том, чтобы использовать функцию подстановки текста в bash, чтобы вырезать последнюю косую черту и все последующее.
Ответ от простых до более сложных случаев исходного вопроса.
Если путь гарантированно заканчивается без косой черты (внутри и снаружи)
Если путь гарантированно заканчивается ровно одной косой чертой (внутри и снаружи)
Если входной путь может заканчиваться нулем или одной косой чертой (не более), и вы хотите, чтобы выходной путь заканчивался без косой черты
Если входной путь может иметь много посторонних слешей и вы хотите, чтобы выходной путь заканчивался без слеша
источник
${BASH_SOURCE[0]}
которому будет полный путь к сценарию, если он не был получен черезsource
или.
.Если
/home/smith/Desktop/Test/../
это то, что вы хотите:как видно здесь .
источник
bash: dirname 'Test': syntax error: invalid arithmetic operator (error token is "'Test'")
. Связанный код тоже неверен.dirname Test
из каталогаTest
в.В зависимости от того, нужны ли вам абсолютные пути, вы можете сделать дополнительный шаг:
источник
используйте это:
export MYVAR="$(dirname "$(dirname "$(dirname "$(dirname $PWD)")")")"
если вы хотите 4-й родительский каталогexport MYVAR="$(dirname "$(dirname "$(dirname $PWD)")")"
если вы хотите третий родительский каталогexport MYVAR="$(dirname "$(dirname $PWD)")"
если вы хотите 2-й родительский каталогисточник
некрасиво, но эффективно
{
}
источник
Начато с идеи / комментария Чарльз Даффи - 17 декабря '14 в 5:32 по теме Получить текущее имя каталога (без полного пути) в скрипте Bash
источник
если по какой - либо причине вы заинтересованы в навигации вверх определенное количество каталогов , которые вы могли бы также сделать:
nth_path=$(cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && cd ../../../ && pwd)
. Это дало бы 3 родительских справочникаисточник