Ein möglicher Weg, dies zu tun
Vor einiger Zeit habe ich eine Funktion speziell für diesen Zweck erstellt, die ich in meinem habe .bashrc
und die in ein Skript umgewandelt werden kann. Sie sollten Positionsparameter nutzen, damit Benutzer Dateinamen in die Befehlszeile einfügen können. Hier ist meine ursprüngliche Funktion:
swap_files() {
if [ $# -ne 2 ]
then
echo "Usage: swap_files file1 file2"
else
local TMPFILE=$(mktemp)
mv -- "$1" "$TMPFILE"
mv -- "$2" "$1"
mv -- "$TMPFILE" "$2"
fi
}
Sie können swap_files(){
Deklaration, local
Schlüsselwort und Abschluss entfernen }
und in ein Skript umwandeln - fügen Sie es einfach #!/bin/bash
oben hinzu. Zugegeben, es gibt Unmengen von Dingen, die verbessert werden können, aber auf der sehr grundlegenden Ebene ist das ungefähr so einfach wie das Austauschen (was in C übrigens häufig gelehrt wird, um Array-Elemente auszutauschen, aber das ist nur ein tangentiales Thema).
#!/bin/bash
if [ $# -ne 2 ]
then
printf "Usage: swap_files file1 file2\n" > /dev/stderr
else
TMPFILE=$(mktemp)
mv -- "$1" "$TMPFILE"
mv -- "$2" "$1"
mv -- "$TMPFILE" "$2"
fi
Denken Sie natürlich daran, die Positionsparameter anzugeben, wenn Dateinamen Leerzeichen enthalten. Wie so:
swap_files 'file 1' 'file 2'
Beachten Sie die Verwendung von --
, um Probleme mit Dateinamen zu vermeiden, die dazu führen -
. Ein besserer Weg wäre es, sich daran zu gewöhnen, Dateien im aktuellen Arbeitsverzeichnis mit zu referenzieren ./
, insbesondere wenn Sie globstar verwenden *
(globstar ist in dieser Frage nicht relevant, aber es ist erwähnenswert, wenn es sich um Dateinamen mit führenden Namen handelt -
). Außerdem ./
ist viel mehr tragbar, da einige Versionen mv
wie auf FreeBSD nicht die haben --
Option.
Wie von terdon in den Kommentaren vorgeschlagen, können wir auch temporäre Dateien im übergeordneten Ordner der ersten Datei erstellen, um zu vermeiden, dass Dateien zwischen Dateisystemen verschoben werden.
#!/bin/bash
if [ $# -ne 2 ]
then
printf "Usage: swap_files file1 file2\n" > /dev/stderr
else
file1_dir=${1%/*}
# just in case there were no slashes removed, assume cwd
if [ "$file1_dir" = "$1" ]; then
file1_dir="."
fi
tmpfile=$(mktemp -p "$file1_dir" )
mv -- "$1" "$tmpfile"
mv -- "$2" "$1"
mv -- "$tmpfile" "$2"
fi
Ihr Skript und Dinge zu verbessern
1. Redundante Variablenzuweisung
file1=$file1
file2=$file2
Dieser Teil weist $file1
... file1
Variable eine Variable zu ; Dies hat zwei Probleme: Das Zuweisen einer Variablen zu sich selbst ist redundant und existiert zunächst nicht. Es gibt keine Deklaration dieser Variablen weiter oben im Skript.
Folgendes passiert, wenn Ihr Benutzer versucht, selbst zitierte Elemente in Ihren read
Befehl einzufügen:
$ read file1 file2
'one potato' 'two potato'
$ echo "$file1"
'one
$ echo "$file2"
potato' 'two potato'
Entsprechend dem Shell-Verhalten teilt die Shell alles, was gelesen wird, auf stdin
und versucht, in jedes Wort in entsprechende Variablen zu passen. Wenn Wörter die Anzahl der Variablen überschreiten, versucht sie, alles in die letzte Variable zu verschieben. Ich würde empfehlen, dass Sie jede Datei einzeln einlesen.
3. Das Kopieren in sich selbst ist ein Fehler
Sie gehen
cp $file1 $file1;
Das wird einen Fehler erzeugen
$ cp input.txt input.txt
cp: 'input.txt' and 'input.txt' are the same file
Vielleicht wolltest du es tun
cp "$file1" "$file1".tmp
Oder nutzen Sie einfach den mktemp
Befehl wie ich. Beachten Sie auch das Zitieren von Variablen, um eine Wortteilung zu verhindern.
Andere lustige Möglichkeiten, es zu tun
Wussten Sie, dass Sie jede Datei mit Umleitung katzen können , um eine Kopie zu erstellen ? Also ist mv
oder cp
nicht der einzige Weg. Etwas wie das:
$ cat ./wallpaper.jpg > wallpaper.jpg.tmp
$ cat ./screenshot.jpg > wallpaper.jpg
$ cat ./wallpaper.jpg.tmp > ./screenshot.jpg
file1=$file1
? Meinten Siefile1=$1
?