¿Archivos específicos de Linux (mv o cp) de una lista de archivos de texto?

34

Tengo un directorio de muchos archivos, algo así como 50,000 pdf y otros archivos en un servidor. Necesito mover los específicos a otro directorio. Puedo generar una lista de los archivos que deben moverse en csv o en cualquier otro formato de texto.

Lo que necesito hacer es ejecutar un script bash y mover o copiar los archivos que figuran en el archivo de texto a otro directorio.

¿Hay una manera fácil de hacer esto? Cualquier sugerencia o recursos serán muy apreciados.

Jestep
fuente
Además, los archivos se nombran aleatoriamente cuando se agregan al directorio. No existe una convención de nomenclatura ni ninguna lógica que pueda usarse para mover archivos específicos.
Jestep

Respuestas:

26

rsync tiene varias opciones que pueden tomar una lista de archivos con el proceso ( --files-from, --include-from, etc.).

Por ejemplo, esto hará el truco:

rsync -a /source/directory --files-from=/full/path/to/listfile /destination/directory
Ignacio Vazquez-Abrams
fuente
2
ejemplo:rsync -a /source/directory --files-from=/full/path/to/listfile /destination/directory
anneb
28

Para evitar un uso inútil de cat(y si no lo usa rsync):

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

Esto manejará cualquier nombre de archivo válido, a menos que contenga una nueva línea, si los archivos se enumeran uno por línea.

Pausado hasta nuevo aviso.
fuente
2
Una desventaja de este enfoque es que si los archivos en la lista contienen nombres de ruta (es decir, no están todos en el mismo directorio), el uso de mvlos colapsará en el mismo directorio de destino. El rsyncenfoque en la respuesta aceptada no sufre esta limitación.
Jason R
Además, probé este comando y xargs se rompería en cualquier archivo que contuviera una comilla simple ("comilla simple sin igual")
James Beninger
Esto funcionó para mí porque realmente quería los archivos de diferentes rutas de origen en el mismo directorio de destino.
PseudoNoise
15
for file in `cat listoffiles`; do mv "$file" /path/of/destination ; done

suponiendo bash, además de listoffilescontener un archivo por línea. Mi única objeción a la ruta rsync es que el OP solicita un método para mover los archivos, no copiarlos. rsync tiene más banderas que una boda real, así que estoy seguro de que puede modificarse aún más para hacerlo, ¡pero a veces más simple es mejor!

MadHatter apoya a Monica
fuente
1
Esta solución me parece la más flexible. Terminé usándolo con rsync en lugar de cp o mv solo porque necesitaba la opción de rutas de archivo relativas.
Spamwich
44
Bien, solo tuve problemas con los espacios, así que lo modifiqué a:while read -r file; do mv "$file" /path/of/destination ; done < listoffiles
user1182474
1
@ user1182474 Gracias y un elegante uso de la redirección de entrada. ¡El método tradicional de mostrar satisfacción con una respuesta es votar a propósito!
MadHatter apoya a Monica
1
@ user1182474 gracias por eso! ¡El último paso en muchas modificaciones tuvo que hacer a ciegas para portar mis utilidades de copia de seguridad de OSX a mi Android!
Charlie Gorichanaz
4

Esto depende del formato del archivo de texto que tenga. Por ejemplo, si tiene la lista de archivos escritos de manera que cada archivo se encuentre en una nueva línea. Puedes usar xargs como:

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

Además, puede usar el findcomando con la -execopción. para copiar / mover los archivos.

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

Rsync tiene el beneficio adicional sobre los comandos cpo mvporque creará automáticamente carpetas si no existen.

Paul Wenzel
fuente
¿Por qué es /path/to/sourcenecesario cuando toma las rutas de la lista de archivos?
bzero
@bzero tal vez la lista de archivos puede contener rutas relativas?
DreadfulWeather
2

Creo que la respuesta rsync es mejor, pero solo para otra opción:

tar -cf - -T FILE_OF_FILENAMES_TO_MOVE.txt |(cd /path/to/new/dir && tar -xvf -)
jj33
fuente
Esto es bueno para un Dockerfile, ya que tar está disponible en la imagen base de ubuntu, pero no en rsync.
Kristianp
1

Copié accidentalmente el contenido completo de un directorio en un directorio de destino en lugar de mover el directorio completo. Esto dio como resultado un directorio de destino desordenado en lugar de agregar el directorio de origen al directorio.

Para solucionar esto, hice lo siguiente:

ls -rt /path/to/cluttered/destination/directory/ > /opt/dircheck/filestomove El comando anterior crea el archivo filetomove que será una lista de todos los contenidos del directorio de destino, ordenados por tiempo inverso, lo que significa más antiguo a más nuevo.

Luego creé un subdirectorio del directorio de destino ahora desordenado para mover las cosas.

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

Luego repetí el listado del directorio, excepto el listado en la pantalla y mostrando más detalles.

ls -lrht /path/to/cluttered/destination/directory/ Esta línea enumera el directorio, ordenado por fecha ascendente (orden inverso por hora) y muestra más información, incluida la marca de fecha / hora de cada archivo en el directorio de destino ahora desordenado. Me refiero a esto, comenzando en la parte superior para mostrar qué directorios y archivos quiero mantener donde estaban. Habrá un vacío en la marca de fecha / hora de los archivos donde comienzan todos los archivos nuevos que no deberían estar allí.

Luego edité el archivo filetomove creado en el primer paso anterior (que está ordenado por fecha) y eliminé los pocos de la lista que estaban allí anteriormente y que quiero quedar del directorio original.

vim /opt/dircheck/filestomove Elimine desde la parte superior todos los archivos que no desea mover.

Luego utilicé el comando enumerado anteriormente en esta publicación para mover los archivos de mi lista al nuevo directorio que hice.

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

Esto movió todos los archivos en una fracción de segundo. (Nota: es posible que no necesite el sudo al principio, esto es una cuestión de permisos de archivo).

Ahora mi directorio de destino original es agradable y limpio y contiene un nuevo directorio con todos los archivos y directorios que lo estaban abarrotando.

John
fuente
1

Si (y solo si), no tiene caracteres desagradables en los nombres de archivo (espacios, líneas nuevas, lo que confundiría a xargs sobre cómo dividir las cosas en argumentos individuales), y genera una lista de archivos separados por líneas nuevas (un archivo por línea), podrías hacer algo como.

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

(En general, mira man xargs , es increíble)

Si su MV particular no tiene la opción -t, también podría hacer algunos trucos como

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

Nota: ninguno de estos funcionará como se espera si hay nombres de archivo con nuevas líneas en ellos.

Kjetil Joergensen
fuente
Sin embargo; vea la respuesta de Ignacio, rsync está hecho para esto.
Kjetil Joergensen
cp, mvy similares no tienen -topción en bsd , y el segundo ejemplo con subshell no funcionó para mí ( /path/to/movese adjunta como el último nombre de archivo)
1
@ w17t - suena como filenames.txt no termina con una nueva línea, agrega nueva línea al final de filenames.txt o hace algo como(cat filenames.txt; echo; echo /path/to/move/files/to) | xargs mv
Kjetil Joergensen
0

Intenta algo como:

cat list.txt | while read line; do mv "$line" /images; done
AliGibbs
fuente
podría haber sido while read line; do mv $line /images; done < list.txt como un solo comando
ignivs
0

Lo siguiente funcionó para mí donde necesitaba copiar todos los archivos PNG desde una ruta específica (y todos los subdirectorios) a una nueva ubicación, preservando la estructura del directorio:

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

Debido a que RSYNC crea primero el espejo de la estructura de directorios, luego sincroniza los archivos, puede terminar con un exceso de carpetas que están vacías. Usé el indicador --prune-empty-dirs para eliminar estos directorios vacíos.

No tengo afiliación, pero pensé que era correcto dar crédito a la fuente que inspiró esta solución: http://techblog.zabuchy.net/2011/transfer-only-selected-file-types-with-rsync/

John Mark Mitchell
fuente