Des fichiers spécifiques Linux (mv ou cp) à partir d'une liste de fichiers texte?


34

J'ai un répertoire de nombreux fichiers, quelque chose comme 50 000 pdf et autres fichiers sur un serveur. Je dois déplacer des spécifiques dans un autre répertoire. Je peux générer une liste des fichiers qui doivent être déplacés au format CSV ou dans tout autre format de texte.

Ce que je dois faire, c'est exécuter un script bash et déplacer ou copier les fichiers répertoriés dans le fichier texte dans un autre répertoire.

Y at-il un moyen facile de le faire? Toute suggestion ou ressource serait grandement appréciée.


En outre, les fichiers sont nommés de manière aléatoire lorsqu'ils sont ajoutés au répertoire. Il n'y a pas de convention de nommage ni de logique pouvant être utilisée pour déplacer des fichiers spécifiques.
Jestep

Réponses:


26

rsync a plusieurs options qui peuvent prendre une liste de fichiers à traiter ( --files-from, --include-from, etc.).

Par exemple, cela fera l'affaire:

rsync -a /source/directory --files-from=/full/path/to/listfile /destination/directory

2
exemple:rsync -a /source/directory --files-from=/full/path/to/listfile /destination/directory
anneb

28

Afin d'éviter une utilisation inutile de cat(et si vous n'utilisez pas rsync):

xargs -a file_list.txt mv -t /path/to/dest

Cela gérera n'importe quel nom de fichier valide, à moins qu'il ne contienne une nouvelle ligne, si les fichiers sont listés un par ligne.


2
Un inconvénient de cette approche est que si les fichiers de la liste contiennent des noms de chemin (c’est-à-dire qu’ils ne sont pas tous dans le même répertoire), leur utilisation mvsera réduite à un seul et même répertoire de destination. L' rsyncapproche dans la réponse acceptée ne souffre pas de cette limitation.
Jason R

En outre, j'ai essayé cette commande et xargs se casserait sur tous les fichiers contenant une citation unique ("citation unique inégalée")
James Beninger

Cela a fonctionné pour moi parce que je voulais en fait les fichiers de différents chemins sources dans le même répertoire cible.
PseudoNoise

15
for file in `cat listoffiles`; do mv "$file" /path/of/destination ; done

en supposant que bash, plus listoffilescontenant un fichier par ligne. Ma seule objection à la route rsync est que le PO demande une méthode pour déplacer les fichiers, pas pour les copier. rsync a plus de drapeaux qu'un mariage royal, donc je suis sûr qu'il peut être modifié pour le faire, mais parfois, plus c'est simple, mieux c'est!


1
Cette solution me semble la plus flexible. J'ai fini par l'utiliser avec rsync au lieu de cp ou mv simplement parce que j'avais besoin de l'option des chemins d'accès aux fichiers relatifs.
Spamwich

4
Bien, j'ai juste eu des problèmes d'espaces, je l'ai donc modifié comme while read -r file; do mv "$file" /path/of/destination ; done < listoffiles
suit

1
@ user1182474 Merci, et une utilisation élégante de la redirection d'entrée. La méthode traditionnelle pour montrer sa satisfaction avec une réponse est de passer au vote, en passant!
MadHatter soutient Monica le

1
@ user1182474 merci pour ça! La dernière étape dans de nombreuses modifications a dû faire un peu aveuglément pour porter mes utilitaires de sauvegarde OSX sur mon Android!
Charlie Gorichanaz

4

Cela dépend du format du fichier texte que vous avez. Par exemple, si vous avez écrit la liste des fichiers de sorte que chaque fichier se trouve sur une nouvelle ligne. Vous pouvez utiliser xargs comme:

$ cat your_text_file | xargs cp -t /path/to/destination

En outre, vous pouvez utiliser la findcommande avec -execoption. copier / déplacer les fichiers.


3
rsync --files-from=file_list.txt /path/to/source/ /path/to/dest/

Rsync présente un avantage supplémentaire par rapport aux commandes cpou mvcar il crée automatiquement des dossiers s’ils n’existent pas.


Pourquoi est /path/to/sourcenécessaire quand il prend les chemins de la liste de fichiers?
bzero

@bzero peut-être que la liste de fichiers peut contenir des chemins relatifs?
DreadfulWeather le

2

Je pense que la réponse rsync est meilleure, mais juste pour une autre option:

tar -cf - -T FILE_OF_FILENAMES_TO_MOVE.txt |(cd /path/to/new/dir && tar -xvf -)

C'est bon pour un fichier Docker, étant donné que tar est disponible dans l'image de base d'ubuntu, mais pas rsync.
Kristianp

1

J'ai accidentellement copié le contenu complet d'un répertoire dans un répertoire de destination au lieu de déplacer le répertoire complet. Cela a abouti à un répertoire de destination encombré à la place du répertoire d'origine ajouté au répertoire.

Pour résoudre ce problème, j'ai fait ce qui suit:

ls -rt /path/to/cluttered/destination/directory/ > /opt/dircheck/filestomove La commande ci-dessus crée le fichier filestomove qui sera une liste de tout le contenu du répertoire de destination, trié en sens inverse par le temps, du plus ancien au plus récent.

Ensuite, j'ai créé un sous-répertoire du répertoire de destination désormais encombré dans lequel déplacer les éléments.

mkdir /path/to/cluttered/destination/directory/newsubdirectory

Ensuite, j'ai répété la liste des répertoires, sauf la liste à l'écran et l'affichage de plus de détails.

ls -lrht /path/to/cluttered/destination/directory/ Cette ligne répertorie le répertoire, trié par date ascendante (tri inversé par heure) et affiche plus d'informations, y compris l'horodatage de chaque fichier dans le répertoire de destination désormais encombré. Je me réfère à cela, en commençant par le haut pour montrer quels répertoires et fichiers je veux garder là où ils étaient. Il y aura un espace dans l'horodatage des fichiers où tous les nouveaux fichiers commencent qui ne devrait pas être là.

Ensuite, j'ai édité le fichier filestomove créé à la première étape ci-dessus (qui est triée par date) et supprimé les quelques-uns de la liste précédemment présents que je souhaite rester dans le répertoire d'origine.

vim /opt/dircheck/filestomove Supprimer du haut tous les fichiers que vous ne voulez pas déplacer.

Ensuite, j'ai utilisé la commande répertoriée précédemment dans cet article pour déplacer les fichiers de ma liste dans le nouveau répertoire que j'ai créé.

sudo xargs -a /opt/dircheck/filestomove mv -t /path/to/cluttered/destination/directory/newsubdirectory

Cela a déplacé tous les fichiers en une fraction de seconde. (Remarque: vous n’avez peut-être pas besoin de sudo au début, c’est une question d’autorisations de fichier).

Maintenant, mon répertoire de destination d'origine est propre et contient un nouveau répertoire avec tous les fichiers et répertoires qui l'encombrent.


1

Si (et seulement si), les noms de fichiers ne contiennent aucun caractère désagréable (espaces, nouvelles lignes, ce qui confondrait xargs sur la façon de diviser les éléments en arguments individuels), et vous générez une liste de fichiers séparés par des nouvelles lignes (un fichier par ligne), vous pouvez faire quelque chose comme.

cat filenames.txt | xargs mv -t /path/to/move/files/to

(En général, voir man xargs , c'est génial)

Si votre mv particulier ne dispose pas de l'option -t, vous pouvez également faire des trucs comme

( cat filenames.txt; echo; echo /path/to/move/files/to ) | xargs mv

Remarque - aucun de ceux-ci ne fonctionnera comme prévu s'il y a des noms de fichiers contenant des nouvelles lignes.


Toutefois; voir la réponse d'Ignacio, rsync est en quelque sorte fait pour ce genre de choses.
Kjetil Joergensen

cp, mvEt autres n'ont pas l' -toption sur bsd « s, et le second exemple avec n'a pas fonctionné sous - shell pour moi ( /path/to/moveest ajouté comme le dernier nom de fichier)

1
@ w17t - on dirait que nomfichier.txt ne se termine pas par une nouvelle ligne, ni ajouter une nouvelle ligne à la fin de nomfichier.txt, ni faire quelque chose qui ressemble à(cat filenames.txt; echo; echo /path/to/move/files/to) | xargs mv
Kjetil Joergensen

0

Essayez quelque chose comme:

cat list.txt | while read line; do mv "$line" /images; done

aurait pu être while read line; do mv $line /images; done < list.txt comme une seule commande
Ignivs

0

Ce qui suit a fonctionné pour moi où je devais copier tous les fichiers PNG d'un chemin spécifique (et de tous les sous-répertoires) vers un nouvel emplacement tout en préservant la structure de répertoires:

rsync -av --prune-empty-dirs --include='*/' --include='*.png' --exclude='*' source/ destination/

Comme RSYNC crée d'abord le miroir de la structure de répertoires, puis synchronise les fichiers, vous pouvez vous retrouver avec des dossiers en excès vides. J'ai utilisé le drapeau --prune-empty-dirs pour supprimer ces répertoires vides.

Je n'ai aucune affiliation, mais je pensais juste de donner crédit à la source qui a inspiré cette solution: http://techblog.zabuchy.net/2011/transfer-only-selected-file-types-with-rsync/

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.