Napisałem skrypt bash, który pobiera plik wejściowy jako argument i czyta go.
Ten plik zawiera ścieżki (w stosunku do jego lokalizacji) do dodatkowych używanych plików.
Chciałbym, aby skrypt przeszedł do folderu zawierającego plik wejściowy, aby wykonać dalsze polecenia.
Jak więc uzyskać folder (i tylko folder) z pliku wejściowego? (W systemie Linux.)
Odpowiedzi:
Aby uzyskać pełną ścieżkę, użyj:
Aby uzyskać katalog pliku:
Możesz również połączyć te dwa elementy:
Jeśli
readlink -f
nie jest dostępny w Twoim systemie, możesz użyć tego * :function myreadlink() { ( cd "$(dirname $1)" # or cd "${1%/*}" echo "$PWD/$(basename $1)" # or echo "$PWD/${1##*/}" ) }
Zauważ, że jeśli potrzebujesz tylko przenieść się do katalogu pliku określonego jako ścieżka względna, nie musisz znać ścieżki bezwzględnej, ścieżka względna jest całkowicie legalna, więc po prostu użyj:
cd $(dirname relative/path/to/file)
jeśli chcesz wrócić (podczas działania skryptu) do oryginalnej ścieżki, użyj
pushd
zamiastcd
, ipopd
kiedy skończysz.* Chociaż
myreadlink
powyższe jest wystarczająco dobre w kontekście tego pytania, ma pewne ograniczenia w stosunku doreadlink
narzędzia sugerowanego powyżej. Na przykład nie podąża poprawnie za łączem do pliku z innym rozszerzeniembasename
.źródło
readlink -f
niestety nie działa na OS X.brew install coreutils
to zdobyć. stackoverflow.com/a/4031502/1022967 .${1%/*}
ani${1##*/}
jako substytutówdirname
ibasename
. Pierwszy przerywa, jeśli nadasz mu prostą nazwę pliku (dirname foo.bar
byłby, poprawnie, be.
), a drugi przerywa katalog kończący się ukośnikiem (basename /foo/bar/
byłby, poprawnie, byłbybar
).basename
/dirname
nie są wbudowane) i zobaczą, że działa na początku, ale nagle w pewnym momencie w przyszłości zepsuje się, bo pozornie nie jest dobre powód. Unikałbym sugerowania tego jako opcji lub stwierdzenia, że tak naprawdę nie jest to substytut kuloodporny.Spójrz na stronę podręcznika
realpath
, używam tego i czegoś takiego:robić to, co wygląda na to, że próbujesz zrobić.
źródło
To zadziała zarówno dla pliku, jak i folderu:
absPath(){ if [[ -d "$1" ]]; then cd "$1" echo "$(pwd -P)" else cd "$(dirname "$1")" echo "$(pwd -P)/$(basename "$1")" fi }
źródło
$cat abs.sh #!/bin/bash echo "$(cd "$(dirname "$1")"; pwd -P)"
Kilka wyjaśnień:
"$1"
dirname "$1"
cd "$(dirname "$1");
przechodzimy do tego względnego reżpwd -P
i uzyskaj absolutną ścieżkę. Ta-P
opcja pozwoli uniknąć dowiązań symbolicznychecho
toNastępnie uruchom skrypt:
źródło
Wypróbuj naszą nową bibliotekę Bash realpath-lib na GitHub, którą udostępniliśmy społeczności do bezpłatnego i nieobciążonego użytku. Jest przejrzysty, prosty i dobrze udokumentowany, więc warto się z niego uczyć. Możesz to zrobić:
get_realpath <absolute|relative|symlink|local file path>
Ta funkcja jest rdzeniem biblioteki:
if [[ -f "$1" ]] then # file *must* exist if cd "$(echo "${1%/*}")" &>/dev/null then # file *may* not be local # exception is ./file.ext # try 'cd .; cd -;' *works!* local tmppwd="$PWD" cd - &>/dev/null else # file *must* be local local tmppwd="$PWD" fi else # file *cannot* exist return 1 # failure fi # reassemble realpath echo "$tmppwd"/"${1##*/}" return 0 # success }
Jest to Bash 4+, nie wymaga żadnych zależności, a także zapewnia get_dirname, get_filename, get_stemname i validate_path.
źródło
Problem z powyższą odpowiedzią dotyczy plików wprowadzanych z „./” jak „./my-file.txt”
Obejście (z wielu):
myfile="./somefile.txt" FOLDER="$(dirname $(readlink -f "${ARG}"))" echo ${FOLDER}
źródło
Używam readlink -f działa na Linuksie
więc
FULL_PATH=$(readlink -f filename) DIR=$(dirname $FULL_PATH) PWD=$(pwd) cd $DIR #<do more work> cd $PWD
źródło
PWD
już istnieje w Bash, a jej wartość jest w rzeczywistości bieżącym katalogiem? I użyj więcej cytatów.