Próbuję napisać skrypt basha. W tym skrypcie chcę, aby użytkownik wprowadził ścieżkę do katalogu. Następnie chcę dołączyć kilka ciągów na końcu tego ciągu i zbudować ścieżkę do niektórych podkatalogów. Na przykład załóżmy, że użytkownik wprowadza następujący ciąg:
/home/user1/MyFolder
Teraz chcę utworzyć 2 podkatalogi w tym katalogu i skopiować tam kilka plików.
/home/user1/MyFolder/subFold1
/home/user1/MyFolder/subFold2
Jak mogę to zrobić?
Odpowiedzi:
Standard POSIX wymaga, aby wiele było
/
traktowanych jako pojedyncze/
w nazwie pliku. Zatem//dir///subdir////file
jest tym samym, co/dir/subdir/file
.W związku z tym połączenie dwóch ciągów w celu zbudowania pełnej ścieżki jest proste, jak:
full_path="$part1/$part2"
źródło
"" + "/" + "Documents"
daje"/Documents"
../
z przodu. Ale może użytkownik chce połączyć ścieżki bezwzględne. W przeciwnym razie mogliby po prostu dodać./
do przodu, aby wymusić względną ścieżkę. Zauważ też, że"$path1/./$path2"
to to samo, co"$path1/$path2"
.#!/bin/bash read -p "Enter a directory: " BASEPATH SUBFOLD1=${BASEPATH%%/}/subFold1 SUBFOLD2=${BASEPATH%%/}/subFold2 echo "I will create $SUBFOLD1 and $SUBFOLD2" # mkdir -p $SUBFOLD1 # mkdir -p $SUBFOLD2
A jeśli chcesz użyć readline, aby ukończyć i tak dalej, dodaj
-e
do wywołaniaread
:read -e -p "Enter a directory: " BASEPATH
źródło
Czy po prostu połączenie części ścieżki nie przyniesie tego, czego chcesz?
$ base="/home/user1/MyFolder/" $ subdir="subFold1" $ new_path=$base$subdir $ echo $new_path /home/user1/MyFolder/subFold1
Następnie możesz utworzyć foldery / katalogi według potrzeb.
Jedną z konwencji jest kończenie ścieżek katalogów
/
(np./home/
), Ponieważ ścieżki zaczynające się od / mogą zostać pomylone z katalogiem głównym. Jeśli//
w ścieżce użyto podwójnego ukośnika ( ), to również jest poprawne. Ale jeśli na żadnej ze zmiennych nie zostanie użyty ukośnik, będzie on niepoprawny (np/home/user1/MyFoldersubFold1
.).źródło
/home/user1/MyFolder/subFold1
więc potrzebujesz inlinenew_path=$base/$subdir
. Ale co zrobić, jeśli podana ścieżka zawiera na końcu „/”?newpath=$base/$subdir/
możesz grać z tym bezpośrednio w linii poleceńPoniższy skrypt łączy kilka (względnych / bezwzględnych) ścieżek (BASEPATH) ze ścieżką względną (SUBDIR):
shopt -s extglob SUBDIR="subdir" for BASEPATH in '' / base base/ base// /base /base/ /base//; do echo "BASEPATH = \"$BASEPATH\" --> ${BASEPATH%%+(/)}${BASEPATH:+/}$SUBDIR" done
Wynik którego jest:
BASEPATH = "" --> subdir BASEPATH = "/" --> /subdir BASEPATH = "base" --> base/subdir BASEPATH = "base/" --> base/subdir BASEPATH = "base//" --> base/subdir BASEPATH = "/base" --> /base/subdir BASEPATH = "/base/" --> /base/subdir BASEPATH = "/base//" --> /base/subdir
Jest
shopt -s extglob
to konieczne tylko, aby pozwolić BASEPATH kończyć się wieloma ukośnikami (co jest prawdopodobnie nonsensem). Bez rozszerzonego globowania możesz po prostu użyć:echo ${BASEPATH%%/}${BASEPATH:+/}$SUBDIR
co spowodowałoby mniej schludne, ale nadal działające:
BASEPATH = "" --> subdir BASEPATH = "/" --> /subdir BASEPATH = "base" --> base/subdir BASEPATH = "base/" --> base/subdir BASEPATH = "base//" --> base//subdir BASEPATH = "/base" --> /base/subdir BASEPATH = "/base/" --> /base/subdir BASEPATH = "/base//" --> /base//subdir
źródło
Pracowałem z moim skryptem powłoki, który musi łączyć ścieżki, tak jak ty.
Chodzi o to, że obie ścieżki
są ważne.
Jeśli chcę dołączyć plik do tej ścieżki, na przykład
nie było natywnej metody (jak os.path.join () w pythonie) w powłoce do obsługi takiej sytuacji.
Ale znalazłem sztuczkę
Na przykład ścieżka podstawowa była przechowywana w zmiennej powłoki
a ostatnia nazwa pliku, do którego chcesz dołączyć, to
Następnie możesz przypisać nową ścieżkę w ten sposób
NEW_PATH=$(realpath ${BASE})/FILE
a wtedy dostaniesz
$ echo $NEW_PATH /path/to/your/home/mydir/myfile
powód jest bardzo prosty, polecenie „realpath” zawsze usuwałoby kończący ukośnik, jeśli to konieczne
źródło
#!/usr/bin/env bash mvFiles() { local -a files=( file1 file2 ... ) \ subDirs=( subDir1 subDir2 ) \ subDirs=( "${subDirs[@]/#/$baseDir/}" ) mkdir -p "${subDirs[@]}" || return 1 local x for x in "${subDirs[@]}"; do cp "${files[@]}" "$x" done } main() { local baseDir [[ -t 1 ]] && echo 'Enter a path:' read -re baseDir mvFiles "$baseDir" } main "$@"
źródło
Powinno to zadziałać dla pustego katalogu (może być konieczne sprawdzenie, czy zaczyna się drugi ciąg, od
/
którego należy traktować jako ścieżkę bezwzględną?):#!/bin/bash join_path() { echo "${1:+$1/}$2" | sed 's#//#/#g' } join_path "" a.bin join_path "/data" a.bin join_path "/data/" a.bin
Wynik:
Odniesienie: Rozszerzenie parametrów powłoki
źródło