J'essaie de déplacer les 8 derniers fichiers du répertoire Documents
vers un autre répertoire, mais je ne souhaite pas les déplacer un par un vers ce répertoire spécifique. Est-il possible de les déplacer avec un substitut de la commande tail
, mais pour des répertoires au lieu de fichiers? Je veux dire que j'aimerais faire quelque chose comme tail -8 ./Documents | mv ./Anotherdirectory
ou avec mv tail -8 ./Documents ./Anotherdirectory
.
En fait, je cherche un moyen intelligent de déplacer rapidement les 8 derniers fichiers (comme indiqué dans ls
) (sans saisir chaque nom) dans l'autre répertoire. Aucune suggestion?
Vous pouvez utiliser for
, qui parcourt les fichiers de manière ordonnée et nous permet d’éviter d’analyser la sortie de find
ou ls
, afin d’éviter les problèmes d’espaces et autres caractères spéciaux dans noms de fichiers. Merci beaucoup à @muru pour l'amélioration de cette situation :)
i=0; j=$(stat ~/Documents/* --printf "%i\n" | wc -l); for k in ~/Documents/*; do if (( (j - ++i) < 8 )); then echo mv -v "$k" ~/AnotherDirectory; fi; done
Testez-le d'abord avec echo
, puis supprimez echo
pour déplacer réellement les fichiers.
En tant que script:
#!/bin/bash
i=0
j=$(stat ~/Documents/* --printf "%i\n" | wc -l )
for k in ~/Documents/*; do
if (( (j - ++i) < 8 )); then
echo mv -v -- "$k" ~/AnotherDirectory
fi
done
encore une fois, supprimez echo
après avoir testé le déplacement réel des fichiers
i=0
indiquant au shell de commencer à itérer à 0j=$(stat ~/Documents/* --printf "%i\n" | wc -l )
ceci définit la variable j
sur un entier égal au nombre total de fichiers du répertoire. Merci à La réponse de Serg à ma propre question sur la manière de compter les fichiers de manière fiable, quels que soient les caractères contenus dans leurs nomsdo if (( (j - ++i) < 8 ))
pour chaque itération de la boucle, vérifiez si le résultat de j
moins le nombre de fois que la boucle a été exécutée est inférieur à 8 et si c'est le casmv -v -- "$k" ~/AnotherDirectory
déplace le fichier dans le nouveau répertoireVous pouvez faire des choses comme celle-ci en utilisant la substitution de commande. Dans Bash:
mv $(ls -d [sort options] source/* | tail -n8) destination
La $(command)
exécutera tout ce qui est contenu dans celle-ci et substituera le texte généré dans la commande externe. Cette commande ls
imprimera le chemin d'accès à chaque fichier du répertoire source trié en fonction des indicateurs que vous spécifiez, un par ligne, afin que tail
ne puisse prendre que les derniers. Ainsi, ce qui précède s’étendrait à
mv source/file1 source/file2 source/file3 ... source/file8 destination
Vous pouvez simplement lancer ls -d [sort options] source/* | tail -n8
pour voir quels fichiers il va copier.
Selon la manière dont vous commandez la sortie de ls
et le nom du fichier, vous pourrez peut-être faire ce que vous cherchez plus simplement en utilisant une variante de mv source/name_* destination
pour copier tout ce qui commence par " name_ "au répertoire de destination.
EDIT: Ce qui précède se casse quand il y a des espaces dans les noms de fichiers. Une alternative plus compliquée pour résoudre ce problème serait
ls -d1 [sort options] source/* | tail -n8 | tr '\n' '\0' | xargs --null mv -t destination
cependant, il utilise toujours l'analyse ls
de la sortie pour obtenir un tri dans un ordre non alphabétique.
de manière similaire à la suggestion de t-mager, vous pouvez utiliser les options de tri de ls et saisir les 8 derniers fichiers dans une liste. Voici vos fichiers:
1 10 2 3 4 5 6 7 8 9
utilisez la commande suivante:for n in `ls|tail -8`; do mv $n ~/temp; done
Je trouve que cela fonctionne aussi: ls -1 [sort options] | tail -n2 | xargs -I {} -n 1 echo "mv \"{}\" ../t2/"
Bien entendu, l'écho doit être supprimé: ls -1 | tail -n2 | xargs -I {} -n 1 mv "{}" ../t2/
Le "{}"
peut être remplacé par '{}'
En fait, comme dernière expérience, supprimer les guillemets doubles fonctionne également. Surprenant, mais testé.