Kann ich es so verwenden mv file1 file2
, dass es nur dort ankommt file1
, file2
wo file2
es nicht existiert?
ich habe es versucht
yes n | mv -i file1 file2
(Hier können Sie mv
fragen, ob file2 überschrieben werden soll, und automatisch mit no antworten), aber neben dem Missbrauch werden -i
mir auch keine netten Fehlercodes angezeigt (immer 141 anstelle von 0, wenn verschoben, und etwas anderes, wenn nicht verschoben).
pipefail
Option aktiviert haben, da 141 der Exit-Status von istyes
, nichtmv
der Grund, hier eine SIGPIPE zu erhalten.-T
dafür.mv
anstelle des von zu verwendenyes
, ist die einfachste Lösung möglicherweisemv -i file1 file2 < <(yes n)
Antworten:
mv -vn file1 file2
. Dieser Befehl wird tun, was Sie wollen. Sie können überspringen,-v
wenn Sie möchten.-v
macht es wortreich - mv sagt dir, dass es eine Datei verschoben hat, wenn es diese verschiebt (nützlich, da die Möglichkeit besteht, dass die Datei nicht verschoben wird)-n
Verschiebt sich nur, wenn file2 nicht existiert.Bitte beachten Sie jedoch, dass dies nicht POSIX ist, wie von ThomasDickey erwähnt .
quelle
strace
rennfrei zu sein. Dies zeigt, dass (auf meinem System) Folgendes verwendet wird: stat ("file2", 0x7ffe3e705d10) = -1 ENOENT (Keine solche Datei oder kein solches Verzeichnis) st_size = 0, ...}) = 0 lstat ("file2", 0x7ffe3e705a10) = -1 ENOENT (Keine solche Datei oder kein solches Verzeichnis) rename ("file1", "file2") = 0 lseek (0, 0, SEEK_CUR) = -1 ESPIPE (unzulässige Suche). Also scheint Umbenennen verwendet zu werden. @ StéphaneChazelas Lösung scheint die richtige zu sein, wenn Sie es wirklich rennfrei machen wollen.renameat2
mv -n
Von
man mv
einem GNU-System aus:Auf einem FreeBSD-System:
quelle
Oder:
Würde nur laufen,
mv
wennfile2
es nicht gibt. Beachten Sie, dass es nicht garantiert , dass einfile2
nicht außer Kraft gesetzt werden, weil einfile2
zwischen dem Test und der entstanden sein könntemv
, aber zur Kenntnis , dass zumindest die aktuellen Versionen von GNUmv
mit-i
oder-n
geben Sie nicht diese Garantie entweder (obwohl die Race - Bedingung schmale da erfolgt die überprüfung innerhalb vonmv
).Auf der anderen Seite ist es portabel, ermöglicht die Unterscheidung zwischen den Fällen und funktioniert unabhängig vom
file2
Dateityp (regulär, Pipe, sogar Verzeichnis ).quelle
renameat2
die Sie einRENAME_NOREPLACE
Flag geben können . Ich glaube, dies prüft atomar die Existenz der Datei und verschiebt dann die Datei.Ein rennfreien Ansatz mit GNU
ln
bereitgestelltfile1
ist nicht vom Typ Verzeichnis :(Mit Ausnahme von Fehlern in einigen Netzwerk-Dateisystemen), die sicherstellen, dass keine
file2
Datei überschrieben wird (oder dass, wenn siefile2
vom Typ Verzeichnis ist,file1
nicht in dieses Verzeichnis verschoben wird), da derlink()
Systemaufruf im Gegensatz zumrename()
Systemaufruf fehlschlägt, wenn die Ziel existiert.Es wird jedoch einen Zwischenzustand geben, in dem die Datei sowohl als
file1
als auch existiertfile2
.Die
-T
Option (immer einlink("file1", "file2")
Even-If-file2
Verzeichnis vom Typ zu erstellen) ist GNU-spezifisch.Sie können auch den folgenden
link
Befehl verwenden:Wenn
file1
es sich jedoch um einen Symlink handelt, handelt es sich abhängig von der Implementierungfile2
entweder um einen Hardlink zu diesem Symlink oder zum Ziel dieses Symlinks (unter Solaris verwenden/usr/sbin/link
, nicht/usr/xpg4/bin/link
).quelle
renameat2
mit FlaggeRENAME_NOREPLACE
atomar ist?Sie können auch angeben,
test -e name
welche Variable true zurückgibt, wenn der Name vorhanden ist (unabhängig von Datei, Verzeichnis oder Symlink).Zum Beispiel:
quelle
ln -s doesnotexist exists; test -e exists || echo "does it really not exist?"
. Dasselbe gilt zum Beispiel fürln -s /var/spool/cron/crontabs/. exists
(und Sie sind kein Root oder Mitglied der Crontab-Gruppe).