web-dev-qa-db-fra.com

Déplacer uniquement les 8 derniers fichiers d'un répertoire vers un autre répertoire

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?

7
Sandra Ross

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

Explication

7
Zanna

Vous 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.

3
t-mager

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

1
xortion

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é.

0
tpb261