BASH copia todos los archivos excepto uno

110

Me gustaría copiar todos los archivos de un directorio excepto uno llamado Default.png. Parece que hay varias formas de hacer esto. ¿Qué te parece más efectivo?

Joe Cannatti
fuente
¿Por qué lo necesita para omitir ese archivo, en lugar de simplemente eliminarlo después de copiarlo? ¿Existe ya en el directorio de destino?
Lasse V. Karlsen
1
Sí, un archivo con el mismo nombre ya está viviendo en el directorio de destino.
Joe Cannatti
@ LasseV.Karlsen: O puede ahorrar el tiempo de copiarlo, si es un archivo grande. Estoy interesado en esto, pero excluyo un directorio en lugar de un archivo.
Nikana Reklawyks

Respuestas:

54

Simple, si src/solo contiene archivos:

find src/ ! -name Default.png -exec cp -t dest/ {} +

Si src/tiene subdirectorios, esto los omite, pero copia archivos dentro de ellos:

find src/ -type f ! -name Default.png -exec cp -t dest/ {} +

Si src/tiene subdirectorios, esto no se repite en ellos:

find src/ -type f -maxdepth 1 ! -name Default.png -exec cp -t dest/ {} +
John Kugelman
fuente
5
Esto resulta ser lo mejor para mí porque parece que OS X se envía sin glob habilitado.
Joe Cannatti
6
@Max \;ejecuta el comando una vez por archivo. +ejecuta el comando una vez y le pasa todos los nombres de archivo a la vez (sujeto al límite de longitud de la línea de comando). +es un poco más eficiente en general.
John Kugelman
149

Debe ser como sigue:

cp -r !(Default.png) /dest

Si copia a una carpeta anidada en la carpeta actual (llamada ejemplo en el caso siguiente), también debe omitir ese directorio:

cp -r !(Default.png|example) /example
Jon
fuente
17
Esto produce -bash:!: Evento no encontrado
Joe Cannatti
¿Está copiando los archivos a una carpeta anidada dentro de la carpeta desde la que está copiando?
Jon
47
Esto requiere shopt -s extglobque funcione, si se ha desactivado.
Barry Kelly
5
Parece que OS X debe usarse shopt -s extglobcomo lo describe @BarryKelly. Con eso, funciona perfectamente.
Kat
Años en Bash y no sabía nada de !()... ¡Hermoso! Para aquellos que, como yo, sienten que es hora de estudiar / revisar bash , aquí están los enlaces relevantes relacionados con esta pregunta / respuesta: shopt / extglob y el patrón .
Brandt
73

rsync ha sido mi reemplazo de cp / scp durante mucho tiempo:

rsync -av from/ to/ --exclude=Default.png

-a, --archive               archive mode; equals -rlptgoD (no -H,-A,-X)
-v, --verbose               increase verbosity
matja
fuente
Si quiero excluir dos archivos diferentes, ¿cómo lo uso?
Pulkit Bansal
múltiples --excluir = argumentos son compatibles. Y no olvides el -rargumento si estás sincronizando directorios
Rian Sanderson
5

Yo solo haría:

cp srcdir/* destdir/ ; rm destdir/Default.png

a menos que los archivos sean grandes. De lo contrario, utilice, por ejemplo,

find srcdir -type f/ |grep -v Default.png$ |xargs -ILIST cp LIST destdir/
nos
fuente
1
El primer comando no es lo que pidió el OP. Si Default.pngexiste en los dos directorios, reemplazará el que está en destdirpor el que está en srcdir, luego eliminará el copiado Default.png. En cambio, el OP quiere mantener lo Default.pngque ya existe destdir.
SnowFrog
2
¿Qué tal default.png ya existe en destdir? Tu solución no funcionará.
Iman Mohamadi
2

Esto funciona muy bien para copiar todo excepto los módulos de nodo :) disfrútelo y gracias a las respuestas anteriores que acabo de agregar. En mi opinión, Rsync es mejor que CP, ya que puede ver la barra de progreso sin pedirla.

   rsync -av fromDirectory/ ToDirectory/ --exclude=node_modules
Josh
fuente
0
cp `ls | grep -v Default.png` destdir
Will Hartung
fuente
5
Es más probable que esto produzca errores que hacer lo que pretendes.
Pausado hasta nuevo aviso.
-1
# chattr +i /files_to_exclude
# cp source destination
# chattr -i /files_to_exclude
Ivan Grynenko
fuente
-2

usar el parámetro de expansión del shell con expresiones regulares

cp /<path>/[^not_to_copy_file]* .

Todo se copiará excepto el not_to_copy_file

- si algo anda mal con esto. Por favor especifica !

alex
fuente
1
Bienvenido a SO. Lamentablemente tu respuesta no es correcta. La expresión de corchetes ( [...]) contiene un conjunto de caracteres para coincidir, mientras que un interlineado ^provocará una coincidencia del complemento de los caracteres enumerados. En el siguiente ejemplo, ni el archivo aparecerá en la lista: touch not_to_copy_file to_copy_file ; ls [^not_to_copy_file]*porque serán excluidos todos los nombres de archivo que comienzan con cualquiera de los siguientes caracteres: _cefilnopty.
rtx13