Wie kann ich Verzeichnisse während einer Kopie in bash / zsh / KSH?
-
13-09-2019 - |
Frage
Ich erhalte die folgenden Meldungen oft, zum Beispiel, wenn dev Dateien zu einem Master-Zweig Bewältigungs
cp: /Users/Masi/gitHub/shells/zsh/dvorak: No such file or directory
cp: /Users/Masi/gitHub/shells/zsh/dvorak2: No such file or directory
Ich möchte über die Schaffung der gegebenen Ordner, so dass mein erster Befehl ausgeführt wird aufgefordert werden, wenn ich ja auf die Frage beantworten (s).
Mein Versuch in Pseudo-Code, wenn ich versuche, eine Datei in ein Verzeichnis zu kopieren, das nicht existiert
if no such a directory exists, then asks users about to create it:
if yes, then mkdir directory AND run the initial command again
else do noting
Probleme
- Um die Warnmeldung zu ändern:? Welche Datei die "Keine solche Datei oder das Verzeichnis" kontrolliert -command
- , um den Pfad in dem Anfangsbefehl UND mkidr Pfad ohne die Datei zu kratzen : Wie der Pfad in dem Anfangsbefehl kratzen würde
- kratzen vom Ende mit dem gewählten Sprache wie AWK: Wie würden Sie das letzte Spiel in dem Pfad entfernen, wenn / das Feldtrennzeichen? Ich bin nicht sicher, wie Sie Anfangsbuchstaben vom Ende mit AWK kratzen können.
Lösung
Hier ist eine Funktion, die ich schrieb, die in zsh, bash oder ksh funktionieren wird.
Hinweis: Es aktiviert das Debuggen (es die Befehle hallt es eher laufen würde, als sie ausgeführt wird). Wenn Sie diese Zeile aus kommentieren, es wird sie tatsächlich ausgeführt werden.
Achtung: . Es wird nicht gründlich getestet worden
Um es zu verwenden, setzen Sie dieses Skript in einer Datei namens cpmd
in /usr/local/bin
(oder an anderer Stelle in Ihrem Pfad). Um es zu aktivieren, von der Shell-Eingabeaufforderung den folgenden Befehl ein (oder fügen Sie es zu Ihrem Startskript - für bash wäre es ~/.bashrc
werden):
source cpmd
Dann können Sie eine Datei mit einem Befehl wie folgt kopieren:
cpmd carparts /home/dave/Documents/nonexistent/newdir/
Weder Verzeichnis „nicht existent“ oder „newdir“ noch nicht. Beiden Verzeichnisse erstellt dann die Datei mit dem Namen „Ersatzteile“ auf „newdir“ kopiert.
Wenn Sie keinen Schrägstrich enthalten ( „/“) am Ende, der letzte Teil als Dateiname behandelt wird und alle nicht vorhandene Verzeichnisse davor erstellt:
cpmd supplies /home/dave/Documents/anothernew/consumables
Das Verzeichnis „anothernew“ wird erstellt, dann „Zubehör“ wird mit den neuen Dateinamen „Verbrauchsmaterialien“ kopiert.
Wenn alle Verzeichnisse im Ziel bereits vorhanden ist, cpmd
wirkt wie der reguläre cp
Befehl.
function cpmd {
# copies files and makes intermediate dest. directories if they don't exist
# for bash, ksh or zsh
# by Dennis Williamson - 2009-06-14
# http://stackoverflow.com/questions/993266/unable-to-make-nosuchdirectory-message-useful-in-zsh
# WARNING: no validation is performed on $1 and $2
# all cp commands below are hardcoded with -i (interactive) to prevent overwriting
if [[ -n $KSH_VERSION ]]
then
alias local=typeset
local func="$0"
local lastchar="${2: -1}"
readcmd () { read "$2?$1"; }
elif [[ -n $ZSH_VERSION ]]
then
local func="$0"
# the following two lines are split up instead of doing "${2[-1]}"
# to keep ksh from complaining when the function is loaded
local dest="$2"
local lastchar="${dest[-1]}"
readcmd () { read "$2?$1"; }
elif [[ -n $BASH_VERSION ]]
then
local func="$FUNCNAME"
local lastchar="${2:(-1)}"
readcmd () { read -p "$1" $2; }
else
echo "cpmd has only been tested in bash, ksh and zsh." >&2
return 1
fi
local DEBUG='echo' # COMMENT THIS OUT to make this function actually work
if [[ ${#@} != 2 ]]
then
echo "$func: invalid number of parameters
Usage:
$func source destination
where 'destination' can include nonexistent directories (which will
be created). You must end 'destination' with a / in order for it to
specify only directories. Without the final slash, the 'source' will
be copied with a new name (the last portion of 'destination'). If you
are copying multiple files and 'destination' is not a directory, the
copy will fail." >&2
return 1
fi
local dir=$(dirname "$2")
local response
local nl=$'\n'
# destination ($2) is presumed to be in one of the following formats:
# .../existdir test 1 (-d "$2")
# .../existdir/existfile test 2 (-f "$2")
# .../existdir/newfile test 3 (-d "$dir" && $lastchar != '/')
# .../existdir/newdir/ (else)
# .../newdir/newdir/ (else)
# .../newdir/newfile (else)
if [[ -d "$2" || -f "$2" || (-d "$dir" && $lastchar != '/') ]]
then
$DEBUG cp -i "$1" "$2"
else
if [[ $lastchar == '/' ]]
then
dir="$2"
fi
local prompt="$func: The destination directory...${nl} ${dir}${nl}...does not exist. Create? (y/n): "
while [[ -z $response ]]
do
readcmd "$prompt" response
case $response in
y|Y) response="Y" ;;
n|N) ;;
*) response=
prompt="$func: Invalid response.${nl} Create destination directory? (y/n): ";;
esac
done
if [[ $response == "Y" ]]
then
$DEBUG mkdir -p "$dir" && $DEBUG cp -i "$1" "$2"
else
echo "$func: Cancelled." >&2
fi
fi
}
Andere Tipps
Die Fehlermeldung wird von dem cp
Befehl kommt, nicht zsh. Wenn Sie die Ausgabe verbessern wollen, Sie gehen die Logik für Kürzen und untersuchen Sie den Pfad haben, schreiben zusammen mit zu überprüfen, ob es existiert oder nicht.
Es gibt Befehle dabei behilflich sein, einen Blick auf Basisnamen (1) und dirname (1).