Copiando múltiples archivos específicos de una carpeta a otra

Tengo una carpeta grande de fotos (miles), y tengo una larga lista de archivos, por nombre de archivo exacto, que necesito copiar en otra carpeta. Quiero saber si hay alguna forma de seleccionar varios archivos específicos de esta carpeta, por nombre, y copiarlos en otra carpeta, usando el terminal, sin copiarlos individualmente.

Simplemente copie varios archivos a la vez desde la línea de comando

Hay varias maneras de lograr esto. Lo más fácil que he visto es usar lo siguiente.

cp /home/usr/dir/{file1,file2,file3,file4} /home/usr/destination/ 

La syntax utiliza el comando cp seguido de la ruta al directorio en el que se encuentran los archivos deseados con todos los archivos que desea copiar entre paréntesis y separados por comas.

Asegúrese de tener en cuenta que no hay espacios entre los archivos. La última parte del comando, /home/usr/destination/ , es el directorio en el que desea copiar los archivos.

o si todos los archivos tienen el mismo prefijo pero diferentes finales, podrías hacer algo como esto:

 cp /home/usr/dir/file{1..4} ./ 

Donde se copiarían el archivo1, el archivo2, el archivo3 y el archivo4.

Por la forma en que formuló la pregunta, creo que esto es lo que está buscando, pero también suena como si estuviera buscando un comando para leer de una lista de archivos y copiarlos todos en un determinado directorio. Si ese es el caso, avísame y editaré mi respuesta.

Tratar duplicados con python

Así que escribí un pequeño script en Python que creo que debería hacer el trabajo. Sin embargo, no estoy seguro de cuán versado está en Python (si está versado), así que intentaré explicar cómo usar este script lo mejor que pueda y, por favor, haga todas las preguntas que necesite.

 import os,sys,shutil ### copies a list of files from source. handles duplicates. def rename(file_name, dst, num=1): #splits file name to add number distinction (file_prefix, exstension) = os.path.splitext(file_name) renamed = "%s(%d)%s" % (file_prefix,num,exstension) #checks if renamed file exists. Renames file if it does exist. if os.path.exists(dst + renamed): return rename(file_name, dst, num + 1) else: return renamed def copy_files(src,dst,file_list): for files in file_list: src_file_path = src + files dst_file_path = dst + files if os.path.exists(dst_file_path): new_file_name = rename(files, dst) dst_file_path = dst + new_file_name print "Copying: " + dst_file_path try: shutil.copyfile(src_file_path,dst_file_path) except IOError: print src_file_path + " does not exist" raw_input("Please, press enter to continue.") def read_file(file_name): f = open(file_name) #reads each line of file (f), strips out extra whitespace and #returns list with each line of the file being an element of the list content = [x.strip() for x in f.readlines()] f.close() return content src = sys.argv[1] dst = sys.argv[2] file_with_list = sys.argv[3] copy_files(src,dst,read_file(file_with_list)) 

Este script debe ser relativamente simple de usar. En primer lugar, copie el código anterior en el progtwig gedit (debe estar preinstalado en Ubuntu) o en cualquier otro editor de texto.

Una vez que haya finalizado, guarde el archivo como move.py en su directorio de inicio (puede ser cualquier directorio, pero para facilitar la instrucción, solo use el directorio de inicio) o agregue el directorio en el que se encuentra el archivo a su PATH. Luego coloque el cd en su directorio de inicio (o en el directorio en el que guardó move.py) desde el terminal y escriba el siguiente comando:

 python move.py /path/to/src/ /path/to/dst/ file.txt 

Esto debería copiar todos los archivos que se enumeran desde el directorio de origen al directorio de destino con duplicados que toman el formato pic (1) .jpg, pic (2) .jpg y así sucesivamente. file.txt debe ser un archivo que enumera todas las imágenes que desea copiar con cada entrada en su propia línea separada.

De ninguna manera este script debe afectar al directorio de origen, sin embargo, solo asegúrese de ingresar las rutas correctas al directorio de origen y destino y lo peor que podría pasar es que copie los archivos en el directorio incorrecto.

Notas

  • Este script asume que todas las imágenes originales están en el mismo directorio. Si desea que compruebe los subdirectorios, también será necesario modificar el script.
  • Si accidentalmente escribe mal un nombre de archivo, la secuencia de comandos escupirá el error
    “el archivo no existe” y le pide que “presione enter” para continuar y el script continuará copiando el rest de la lista.
  • No olvide el final / en el camino a la fuente
    Directorio y ruta al directorio de destino. De lo contrario, el script le devolverá un error.

Quizás me esté perdiendo un detalle de su pregunta, pero las respuestas dadas parecen excesivas. Si desea una solución de línea de comandos y no un script, por qué no:

 cd /path/to/src/ cp -t /path/to/dst/ file1 file2 file3 ... 

Lo bueno de hacerlo de esta manera es que puedes completar con tabulación los nombres de archivo

Aquí hay una solución de bash pura. Leerá los nombres de archivo de un archivo de entrada (uno por línea) y copiará cada uno de ellos, cambiando el nombre de los duplicados.

 #!/usr/bin/env bash ## The destination folder where your files will ## be copied to. dest="bar"; ## For each file path in your input file while read path; do ## $target is the name of the file, removing the path. ## For example, given /foo/bar.txt, the $target will be bar.txt. target=$(basename "$path"); ## Counter for duplicate files c=""; ## Since $c is empty, this will check if the ## file exists in target. while [[ -e "$dest"/"$target"$c ]]; do echo "$target exists"; ## If the target exists, add 1 to the value of $c ## and check if a file called $target$c (for example, bar.txt1) ## exists. This loop will continue until $c has a value ## such that there is no file called $target$c in the directory. let c++; target="$target"$c; done; ## We now have everything we need, so lets copy. cp "$path" "$dest"/"$target"; done 

Guarde este script en una carpeta en su $PATH y $PATH con la lista de rutas como entrada:

 auto_copy.sh < file_paths.txt 

También puedes ejecutar todo como un comando desde la terminal:

 while read path; do target=$(basename "$path"); c=""; while [[ -e bar/"$target"$c ]]; do echo "$target exists"; let c++; target="$target"$c; done; cp "$file" bar/"$target"; done < file_names; 

Según la descripción de la pregunta, mi entendimiento es que:

  • hay una lista de archivos, probablemente un archivo de texto input.txt
  • la lista contiene solo nombres de archivos
  • Hay un directorio particular donde se encuentran estos nombres de archivo.

Así, se puede hacer uso del siguiente comando:

 xargs -I % --arg-file=input.txt cp /path/to/origin_dir/% /path/to/destination 

Explicación:

  • -I % especifica el símbolo para el archivo actualmente procesado para ser utilizado dentro del comando
  • --arg-file=input.txt especifica que se lleven argumentos al comando desde input.txt
  • cp /path/to/origin_dir/% /path/to/destination/ ejecutará el comando cp con /path/to/origin_dir/% siendo reemplazado por /path/to/origin_dir/ y el nombre del archivo procesado actualmente.

Ejemplo práctico:

 $ cat input.txt file2.txt file1.txt file3.txt $ ls ./docs file1.txt file2.txt file3.txt $ xargs -I % --arg-file=input.txt cp ./docs/% ./docs_destination/ $ ls ./docs_destination/ file1.txt file2.txt file3.txt