Puis-je utiliser mv file1 file2
d'une manière qui ne bouge que file1
à file2
si file2
n'existe pas?
J'ai essayé
yes n | mv -i file1 file2
(cela permet à mv
de demander si file2 doit être remplacé et de répondre automatiquement non) mais en plus d'abuser -i
cela ne me donne pas non plus de bons codes d'erreur (toujours 141 au lieu de 0 si déplacé et autre chose s'il n'est pas déplacé)
mv -vn file1 file2
. Cette commande fera ce que vous voulez. Vous pouvez ignorer -v
si tu veux.
-v
le rend verbeux - mv vous dira qu'il a déplacé le fichier s'il le déplace (utile, car il est possible que le fichier ne soit pas déplacé)
-n
se déplace uniquement si le fichier2 n'existe pas.
Veuillez noter cependant que ce n'est pas POSIX comme mentionné par ThomasDickey .
mv -n
De man mv
sur un système GNU:
-n, --no-clobber
n'écrase pas un fichier existant
Sur un système FreeBSD:
-n
N'écrasez pas un fichier existant. (L'option -n remplace toutes les options -f ou -i précédentes.)
if [ ! -e file2 ] && [ ! -L file2 ]
then
mv file1 file2
# else echo >&2 there is already a file2 file.
fi
Ou:
if ! ls -d file2 > /dev/null 2>&1
then
mv file1 file2
fi
N'exécuterait que mv
si file2
n'existe pas. Notez qu'il ne garantit pas qu'un file2
ne sera pas remplacé car un file2
aurait pu être créé entre le test et le mv
, mais notez qu'au moins les versions actuelles de GNU mv
avec -i
ou -n
ne donne pas non plus cette garantie (bien que la condition de concurrence y soit plus étroite puisque la vérification est effectuée dans mv
).
À l'autre extrémité, il est portable, vous permet de faire la distinction entre les cas, et fonctionne quel que soit le type de file2
fichier (normal, pipe, pair répertoire).
Une approche sans course avec GNU ln
à condition que file1
Ne soit pas de type répertoire:
ln -PT file1 file2 && rm file1
(À l'exception des bogues dans certains systèmes de fichiers réseau), cela garantit qu'aucun fichier file2
Ne sera écrasé (ou que si file2
Est de type répertoire, file1
Ne sera pas déplacé dedans), car l'appel système link()
, contrairement à l'appel système rename()
échouera si la cible existe.
Cependant, il y aura un état intermédiaire où le fichier existe à la fois sous file1
Et file2
.
L'option -T
(Pour toujours faire une link("file1", "file2")
même si file2
Est de type répertoire) est spécifique à GNU.
Vous pouvez également utiliser la commande link
:
link file1 file2 && rm file1
Cependant, si file1
Est un lien symbolique, selon l'implémentation, file2
Sera soit un lien dur vers ce lien symbolique, soit vers la cible de ce lien symbolique (sur Solaris, utilisez /usr/sbin/link
, pas /usr/xpg4/bin/link
).
Vous pouvez aussi utiliser test -e name
qui retournera vrai si le nom existe (quel que soit le fichier, le répertoire ou le lien symbolique).
Par exemple:
touch file
mkdir dir
ln -s file symlink
test -e file && echo file exists
test -e dir && echo dir exists
test -e symlink && echo symlink exists
test -e file || echo you wont see this echo
test -e doesnotexist || echo doesnotexist does not exist...