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

97

Tengo una gran carpeta de imágenes (miles), y tengo una larga lista de archivos, por nombre de archivo exacto, que necesito copiar a otra carpeta. Quiero saber si hay una manera de seleccionar varios archivos específicos de esta carpeta, por nombre, y copiarlos en otra carpeta, usando la terminal, sin copiarlos individualmente.

    
pregunta Someone with far too many pict 01.08.2013 - 05:44

4 respuestas

132

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

Hay varias formas 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 sintaxis usa el comando cp seguido de la ruta al directorio donde se encuentran los archivos deseados, con todos los archivos que desea copiar entre corchetes 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 terminaciones, podría hacer algo como esto:

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

donde se copiarán el archivo1, el archivo2, el archivo3 y el archivo4.

De cómo redactó la pregunta, creo que esto es lo que está buscando, pero también parece que podría estar buscando un comando para leer en una lista de archivos y copiarlos a un determinado directorio. Si ese es el caso, hágamelo saber y editare mi respuesta.

Manejo de duplicados con python

Así que escribí un pequeño script de Python que creo que debería hacer el trabajo. Sin embargo, no estoy seguro de cuán versado estás en Python (si es que sí versado), así que trataré de explicar cómo usar este script lo mejor que pueda y haré tantas preguntas como necesites.

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. Primero, copie el código anterior en el programa gedit (debe estar preinstalado en Ubuntu) o cualquier otro editor de texto.

Una vez que se haya completado, 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 al archivo está contenido en tu PATH. Luego cd a su directorio de inicio (o cualquier directorio que haya guardado move.py in) 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 tomando el formato pic (1) .jpg, pic (2) .jpg, etc. file.txt debería ser un archivo que enumera todas las imágenes que desea copiar con cada entrada en su propia línea separada.

De ninguna manera esta secuencia de comandos debería afectar al directorio de origen, sin embargo, asegúrese de ingresar las rutas correctas al directorio de origen y de 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 revise los subdirectorios también la secuencia de comandos tendrá que ser modificado.
  • Si accidentalmente escribe incorrectamente un nombre de archivo, el script escupirá el error
    "el archivo no existe" y le pide que "presione enter" para continuar y el script continuará copiando el resto de la lista.
  • No olvide el porcentaje final / tanto en la ruta a la fuente

    directorio y ruta al directorio de destino. De lo contrario, el script te escupirá un error.
respondido por el Bryan 01.08.2013 - 06:04
26

Tal vez me falta un detalle de tu 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 puede tab completar los nombres de archivo

    
respondido por el Ross Allen 25.08.2016 - 17:48
6

Aquí hay una solución pura bash. Leerá los nombres de archivo de un archivo de entrada (uno por línea) y copiará cada uno de ellos, renombrando 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 llámelo 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;
    
respondido por el terdon 01.08.2013 - 15:24
0

Según la descripción de la pregunta, entiendo que:

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

Por lo tanto, uno puede usar el siguiente comando:

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

Explicación:

  • -I % especifica el símbolo para que el archivo actualmente procesado se use dentro del comando
  • --arg-file=input.txt especifica para tomar argumentos al comando de input.txt
  • cp /path/to/origin_dir/% /path/to/destination/ llevará a cabo el comando cp con /path/to/origin_dir/% reemplazado por /path/to/origin_dir/ y el nombre del archivo actualmente procesado.

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
    
respondido por el Sergiy Kolodyazhnyy 26.05.2018 - 07:32

Lea otras preguntas en las etiquetas