Ich versuche ein Bash-Skript zu schreiben. In diesem Skript soll der Benutzer den Pfad eines Verzeichnisses eingeben. Dann möchte ich am Ende dieser Zeichenfolge einige Zeichenfolgen anhängen und einen Pfad zu einigen Unterverzeichnissen erstellen .. _. Beispiel: Der Benutzer gibt eine Zeichenfolge wie folgt ein:
/home/user1/MyFolder
Jetzt möchte ich zwei Unterverzeichnisse in diesem Verzeichnis erstellen und einige Dateien dort kopieren.
/home/user1/MyFolder/subFold1
/home/user1/MyFolder/subFold2
Wie kann ich das machen?
Der POSIX-Standard schreibt vor, dass mehrere /
in einem Dateinamen als ein /
behandelt werden. Somit ist //dir///subdir////file
dasselbe wie /dir/subdir/file
.
Eine Verkettung von zwei Strings zum Erstellen eines vollständigen Pfads ist einfach:
full_path="$part1/$part2"
#!/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
Und wenn Sie readline verwenden möchten, um die Fertigstellung zu erreichen, fügen Sie dem Aufruf von read
einen -e
hinzu:
read -e -p "Enter a directory: " BASEPATH
Wird der Teil Ihres Pfads nicht einfach das erreichen, was Sie wollen?
$ base="/home/user1/MyFolder"
$ subdir="subFold1"
$ new_path=$base$subdir
$ echo $new_path
/home/user1/MyFoldersubFold1
sie können dann die Ordner/Verzeichnisse nach Bedarf erstellen.
Das folgende Skript verkettet mehrere (relative/absolute) Pfade (BASEPATH) mit einem relativen Pfad (SUBDIR):
shopt -s extglob
SUBDIR="subdir"
for BASEPATH in '' / base base/ base// /base /base/ /base//; do
echo "BASEPATH = \"$BASEPATH\" --> ${BASEPATH%%+(/)}${BASEPATH:+/}$SUBDIR"
done
Die Ausgabe davon ist:
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
Der shopt -s extglob
ist nur erforderlich, damit BASEPATH auf mehreren Schrägstrichen enden kann (was wahrscheinlich Unsinn ist). Ohne erweitertes Globing können Sie einfach Folgendes verwenden:
echo ${BASEPATH%%/}${BASEPATH:+/}$SUBDIR
was dazu führen würde, dass das weniger ordentlich ist, aber trotzdem funktioniert:
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
#!/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 "[email protected]"
Ich habe mit meinem Shell-Skript herumgearbeitet, das einige Pfadverknüpfungen wie Sie ausführen muss.
Die Sache ist, beide Wege mögen
/data/foo/bar
/data/foo/bar/
sind gültig.
Wenn ich eine Datei an diesen Pfad anhängen möchte
/data/foo/bar/myfile
es gab keine systemeigene Methode (wie os.path.join () in Python) in Shell, um mit einer solchen Situation umzugehen.
Aber ich habe einen Trick gefunden
Beispielsweise wurde der Basispfad in einer Shell-Variablen gespeichert
BASE=~/mydir
und der letzte Dateiname, dem Sie beitreten möchten, war
FILE=myfile
Dann können Sie Ihren neuen Pfad so zuweisen
NEW_PATH=$(realpath ${BASE})/FILE
und dann wirst du bekommen
$ echo $NEW_PATH
/path/to/your/home/mydir/myfile
der Grund ist ganz einfach: Der Befehl "realpath" schneidet den abschließenden Schrägstrich bei Bedarf immer für Sie ab
Dies sollte für ein leeres Verzeichnis funktionieren. (Möglicherweise müssen Sie überprüfen, ob die zweite Zeichenfolge mit /
beginnt, der als absoluter Pfad behandelt werden soll.):
#!/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
Ausgabe:
a.bin
/data/a.bin
/data/a.bin
Referenz: Shell-Parametererweiterung