¿Cómo copiar algunos, pero no todos los archivos?

54

Por lo tanto, puede usarlo *como comodín para todos los archivos cuando lo use cpdentro del contexto de un directorio. ¿Hay alguna manera de copiar todos los archivos excepto el xarchivo?

Chad Harrison
fuente

Respuestas:

42

En bashpuedes usar extglob:

 $ shopt -s extglob  # to enable extglob
 $ cp !(b*) new_dir/

donde !(b*)excluir todos los b*archivos.

Más tarde puede deshabilitar extglobcon

 $ shopt -u extglob
prisa
fuente
¿Sabes si hay algo equivalente para el shell tcsh?
Levon
Lamentablemente no. Parece que findes la única manera de tcsh:find . -maxdepth 1 ! -name "exclude*" -exec cp -t destination {} \+
rush
50

Rsync maneja esto muy bien.

Ejemplo copiar todo: rsync -aP /folder1/* /folder/2

Ejemplo copiar todo con exclusión: rsync -aP --exclude=x /folder1/* /folder2/

El -aPinterruptor:

a: similar a cp -a, recursivo, etc. P: muestra el progreso, una buena característica de rsync.

Tim
fuente
55
Y vea esta respuesta para obtener una guía breve de las listas de exclusión de rsync comunes.
Gilles 'SO- deja de ser malvado'
1
En darwin / MacOS, use en -rPlugar de -aPsi desea recurrir. -aes para archivar. No estoy seguro si esto cambió o si es diferente en MacOS.
jpoveda
rsynctiene la opción de hacerlo recursivo. Ejemplo: rsync --recursive -P --exclude=x /folder1/* /folder2/. (Probado solo en Ubuntu)
n1k31t4
12

Esta no es una característica de cp, es una característica de su shell (se expande *para que signifique todos los archivos que no son puntos), por lo que la respuesta depende de qué shell esté usando. Por ejemplo, zshadmite esta sintaxis:

$ cp ^x /path/to/destination

Donde ^xsignifica "todos los archivos excepto x"

También puede combinar patrones de selección y eliminación de selección, por ejemplo, para copiar todos los archivos wav excepto los que contienen xyz, puede usar:

cp *.wav~*xyz*
Michael Mrozek
fuente
¿Algún comentario sobre bash?
Chad Harrison
@hydroparadise No sé mucho sobre bash, pero esta respuesta parece cubrirlo
Michael Mrozek
¿Qué hay de tcsh? ¿Nadie sabe?
Levon
4

También se podría hacer en una capa de bourne antigua (portátil / compatible) de varias maneras con herramientas estándar de una manera mucho menos elegante que usando comandos avanzados de shell o comandos con opciones de exclusión incorporadas.

Si no hay demasiados archivos (y no con nombres que incluyen espacios y / o saltos de línea), esta podría ser una manera:

cp `ls | egrep -v '^excludename$'` destdir/.

Claro, bashy las herramientas GNU son geniales y poderosas, pero aún no siempre están disponibles. Si tiene la intención de ponerlo en un script portátil, lo recomendaría findcomo en el comentario de Rush.

MattBianco
fuente
2
Me parece que la última parte de su respuesta solo distrae del tema en cuestión. Además, "Unix" ya no es el estándar de oro (si alguna vez lo fue). Simplemente no es tan relevante si algo es "Unix" o ya no, a pesar de que el título de este sitio es "Unix y Linux".
Alexander
2
OKAY. En su lugar, moví el comentario aquí: Unix no es GNU. Estoy de acuerdo en que la "unicidad" de las cosas no es muy interesante, pero sigo creyendo en la portabilidad y saber un poco sobre su historia.
MattBianco
Totalmente de acuerdo contigo allí.
Alexander
2

Si desea copiar todo en una carpeta (incluidas las subcarpetas) a un subdirectorio particular:

cp -R $(ls | grep -v '^subdir$') subdir/

Funciona con sh, bash, zsh (al menos).

usuario2707671
fuente
1
Convencerme, esta no es la misma intención quecp -R * subdir/
roaima
1
Si utiliza ese comando "cp -R * subdir /", bash / zsh intentará copiar 'subdir' de forma recurrente. Terminas con un error: "nombre demasiado largo (no copiado)".
user2707671
Buen punto. Su sugerencia intenta evitar la advertencia de cp(no de bash/ sh), " cp: cannot copy a directory, ‘subdir’, into itself, ‘subdir/subdir’". Sin embargo, la copia se completa correctamente. Desafortunadamente, su variante se rompe con cualquier nombre de archivo que contenga un espacio o puntuación sensible al shell. Ver unix.stackexchange.com/q/128985/135943
roaima el
-1

extglob Es la mejor manera hasta ahora, supongo.

Otra forma es usar cp $(ls --ignore=x) subdir/

Edwin Lee
fuente
Esto se romperá dada cualquier forma de caracteres especiales en los nombres de archivo. (Espacios, líneas nuevas, $etc.) Nunca analice la salida de ls. unix.stackexchange.com/q/128985/135943
Comodín el