¿Cómo usar el comando 'cp' para excluir un directorio específico?
411
Quiero copiar todos los archivos en un directorio excepto algunos archivos en un subdirectorio específico. He notado que el comando 'cp' no tenía una opción --exclude. Entonces, ¿cómo puedo lograr esto?
Tenga en cuenta que el directorio thefoldertoexcludedespués de --excludela opción es relativa a la sourcefolder, es decir, sourcefolder/thefoldertoexclude.
También puede agregar -npara la ejecución en seco para ver qué se copiará antes de realizar una operación real, y si todo está bien, elimínelo -nde la línea de comandos.
De acuerdo, no se puede superar la simplicidad y el poder de--exclude
Mateo Wilcoxson
31
thefoldertoexcludeCuál es el relativo al sourcefolderdirectorio de trabajo actual? gracias
Beebee
46
Es relativo a la carpeta de origen. Esto excluirá la carpeta fuente / .git de ser copiada. rsync -r
--excluye el
15
Tal vez me equivoque, pero creo que es una buena práctica agregar "interruptores" antes de "parámetros". También la página del manual de informes rsync --excluye utilizable como con la sintaxis "=" o sin ella. Por lo tanto, para estandarizar en todos los sistemas operativos, usaría rsync -av --progress --exclude="thefoldertoexclude" sourcefolder /destinationfolder, de todos modos, votar a favor de rsync en lugar de find, ya que puede usar fácilmente rutas absolutas para la fuente mientras que en find es más complicado ya que usa {}en dst.
Xavi Montero
1
@mamun Por supuesto, por ejemplo, del servidor remoto a la máquina local: $ rsync [email protected]:/var/www/mypage /var/www/mylocalpage/o de local a remoto$ rsync /var/www/mylocalpage/ [email protected]:/var/www/mypage
sobi3ch
84
Bueno, si cada utilidad de archivo unix-ish tuviera que realizar la exclusión de ciertos patrones de nombre de archivo (como cp, mv, rm, tar, rsync, scp, ...), se produciría una inmensa duplicación de esfuerzos. En cambio, tales cosas se pueden hacer como parte de la globulación , es decir, por su caparazón.
Así que solo pones un patrón dentro !()y niega el partido. El patrón puede ser arbitrariamente complejo, comenzando por la enumeración de rutas individuales (como lo muestra Vanwaril en otra respuesta): !(filename1|path2|etc3)a cosas similares a expresiones regulares con estrellas y clases de personajes. Consulte la página de manual para más detalles.
Creo que necesita el -pathargumento para probar las jerarquías de ruta, no -iname
James Murty
3
Y también necesitará un punto y coma al final:find . -type f -not -path '*/not-from-here/*' -exec cp '{}' '/dest/{}' \;
Matthew Wilcoxson
1
Wow, no me deja: "Las ediciones deben tener al menos 6 caracteres".
Matthew Wilcoxson
1
@MatthewWilcoxson Meh. Esas restricciones se levantarán tan pronto como ganes un poco más de reputación. Edité la respuesta en consecuencia. ¡Gracias de nuevo!
Linus Kleen
1
@Henning ¿por qué no rsync? ¡Porque puede no estar presente en el sistema! mientras find, cpsiempre está en sus lugares. ¿O eres de gente que instaló 2 gigas de cosas para hacer cosas simples?
Hizo una función de shell que simplifica el uso de la ruta de origen personalizada y la exclusión de un solo archivo o directorio: # $1 = source path # $2 = destination path # $3 = filter copy_from_source_to_destination_except_filter() { cp -r $(ls -A $1 | grep -v -w $3 | awk -v path=$1 '{printf "%s/%s ", path, $1}') $2 }
ElectRocnic
falla con directorios con espacios
Sérgio
27
La forma más fácil que encontré, donde puedes copiar todos los archivos, excepto los archivos y carpetas, simplemente agregando sus nombres entre paréntesis:
rsyncEn realidad es bastante complicado. tiene que hacer múltiples pruebas para que funcione.
Digamos que usted quiere copiar /var/www/htmla /var/www/dev, pero necesidad de excluir/var/www/html/site/video/ directorio tal vez debido a su tamaño. El comando sería:
Se /necesita la última barra diagonal en la fuente, de lo contrario, también copiará el directorio fuente en lugar de su contenido y se convertirá /var/www/dev/html/xxxx, lo que tal vez no sea lo que desea.
La --excluderuta es relativa a la fuente directamente. Incluso si pones la ruta absoluta completa, no funcionará.
-ves detallado, -aes para el modo de archivo, lo que significa que desea recurrencia y desea preservar casi todo.
cuidado con las entradas de directorio que contienen espacios.
Paulo Scardine
3
Esta es una modificación de la respuesta de Linus Kleen. Su respuesta no funcionó para mí porque habría un. agregado delante de la ruta del archivo que a cp no le gusta (la ruta se vería como fuente / .destination / file).
Tal vez no sea bonito, pero esta es la única opción que he encontrado aquí que funciona con cpun shell POSIX estándar como sh.
tomekwi
1
Esta respuesta está dramáticamente subestimada. Esta es la respuesta más compatible, fácil de leer y fácil de entender. Felicitaciones, no sé por qué no pensé en eso.
Robert Talada
Gracias @RobertTalada, ¿hasta dónde llegará la respuesta a partir de ahora? ️🌈
lama12345
0
Utilizo un bucle "do while" para leer la salida del comando find. En este ejemplo, estoy haciendo coincidir (en lugar de excluir) ciertos patrones, ya que hay un número más limitado de coincidencias de patrones que quiero que no quiero. Puede revertir la lógica con un -no delante de las banderas -iname:
Utilizo lo anterior para copiar todos los archivos de tipo de música que son más nuevos en mi servidor que los archivos en un Western Digital TV Live Hub que he montado en / media / wd. Utilizo lo anterior porque tengo muchos archivos DVD, mpegs, etc. que quiero excluir Y porque por alguna razón parece que rsync se está copiando, pero después de mirar el dispositivo wd, los archivos no están ahí a pesar de que no errores durante el rsync con este comando:
La primera parte lstodos los archivos pero archivos específicos ocultos con bandera -I. La salida de lsse utiliza como entrada estándar para la segunda parte. xargsconstruir y ejecutar comandos cp -rf -t destdirdesde la entrada estándar. la bandera-r significa copiar directorios de forma recursiva, -fsignifica copiar archivos a la fuerza que sobrescribirán los archivos en destdir, -tespecifique la copia del directorio de destino.
tar -c | tar -x
?Respuestas:
rsync es rápido y fácil:
Puedes usar
--exclude
múltiples veces.Tenga en cuenta que el directorio
thefoldertoexclude
después de--exclude
la opción es relativa a lasourcefolder
, es decir,sourcefolder/thefoldertoexclude
.También puede agregar
-n
para la ejecución en seco para ver qué se copiará antes de realizar una operación real, y si todo está bien, elimínelo-n
de la línea de comandos.fuente
--exclude
thefoldertoexclude
Cuál es el relativo alsourcefolder
directorio de trabajo actual? graciasrsync -av --progress --exclude="thefoldertoexclude" sourcefolder /destinationfolder
, de todos modos, votar a favor de rsync en lugar de find, ya que puede usar fácilmente rutas absolutas para la fuente mientras que en find es más complicado ya que usa{}
en dst.$ rsync [email protected]:/var/www/mypage /var/www/mylocalpage/
o de local a remoto$ rsync /var/www/mylocalpage/ [email protected]:/var/www/mypage
Bueno, si cada utilidad de archivo unix-ish tuviera que realizar la exclusión de ciertos patrones de nombre de archivo (como cp, mv, rm, tar, rsync, scp, ...), se produciría una inmensa duplicación de esfuerzos. En cambio, tales cosas se pueden hacer como parte de la globulación , es decir, por su caparazón.
golpetazo
man 1 bash
, / extglob .Ejemplo:
Así que solo pones un patrón dentro
!()
y niega el partido. El patrón puede ser arbitrariamente complejo, comenzando por la enumeración de rutas individuales (como lo muestra Vanwaril en otra respuesta):!(filename1|path2|etc3)
a cosas similares a expresiones regulares con estrellas y clases de personajes. Consulte la página de manual para más detalles.zsh
man 1 zshexpn
, / generación de nombre de archivo .Puedes hacer
setopt KSH_GLOB
y usar patrones tipo bash. O,Entonces
x~y
coincide con el patrónx
, pero excluye el patróny
. Una vez más, para más detalles, consulte la página de manual.pez nuevo!
La concha de pescado tiene una respuesta mucho más bonita a esto:
Bonificación pro-tip
Escriba
cp *
, presione CtrlX*y solo vea lo que sucede. no es dañino lo prometofuente
zsh
aunque funciona.setopt -u extglob
.¿Por qué usar
rsync
cuando puedes hacer:Esto supone que la estructura del directorio de destino es la misma que la del origen.
fuente
-path
argumento para probar las jerarquías de ruta, no -inamefind . -type f -not -path '*/not-from-here/*' -exec cp '{}' '/dest/{}' \;
rsync
? ¡Porque puede no estar presente en el sistema! mientrasfind
,cp
siempre está en sus lugares. ¿O eres de gente que instaló 2 gigas de cosas para hacer cosas simples?fuente
# $1 = source path # $2 = destination path # $3 = filter copy_from_source_to_destination_except_filter() { cp -r $(ls -A $1 | grep -v -w $3 | awk -v path=$1 '{printf "%s/%s ", path, $1}') $2 }
La forma más fácil que encontré, donde puedes copiar todos los archivos, excepto los archivos y carpetas, simplemente agregando sus nombres entre paréntesis:
fuente
-bash: !: event not found
Ampliando el comentario de mvds , esto funciona para mí
fuente
Es relativo al directorio fuente.
Esto excluirá el directorio
source/.git
de ser copiado.fuente
rsync
y primero pruébelo con la opción -n para ver qué se va a copiar
fuente
Supongo que estás usando bash o dash. ¿Funcionaría esto?
Hacer un ls excluyendo los archivos que no desea, y usar eso como el primer argumento para cp
fuente
ls
y simplemente hacerlocp !(file1|file1) dest
.cp $(ls folder/!exclude_folder0|exclude_folder1)) dest
Otra opción más simple es instalar y usar rsync que tiene una opción --exclude-dir, y puede usarse tanto para archivos locales como remotos.
fuente
rsync
En realidad es bastante complicado. tiene que hacer múltiples pruebas para que funcione.Digamos que usted quiere copiar
/var/www/html
a/var/www/dev
, pero necesidad de excluir/var/www/html/site/video/
directorio tal vez debido a su tamaño. El comando sería:rsync -av --exclude 'sites/video' /var/www/html/ /var/www/dev
Algunas advertencias :
/
necesita la última barra diagonal en la fuente, de lo contrario, también copiará el directorio fuente en lugar de su contenido y se convertirá/var/www/dev/html/xxxx
, lo que tal vez no sea lo que desea.La
--exclude
ruta es relativa a la fuente directamente. Incluso si pones la ruta absoluta completa, no funcionará.-v
es detallado,-a
es para el modo de archivo, lo que significa que desea recurrencia y desea preservar casi todo.fuente
Editar: olvidó excluir también la ruta de destino (de lo contrario, se copiaría recursivamente).
fuente
Esta es una modificación de la respuesta de Linus Kleen. Su respuesta no funcionó para mí porque habría un. agregado delante de la ruta del archivo que a cp no le gusta (la ruta se vería como fuente / .destination / file).
Este comando funcionó para mí:
find . -type f -not -path '*/exlude-path/*' -exec cp --parents '{}' '/destination/' \;
el comando --parents conserva la estructura del directorio.
fuente
fuente
Simplemente muévalo temporalmente a un directorio oculto (y cámbiele el nombre después, si lo desea).
fuente
cp
un shell POSIX estándar comosh
.Utilizo un bucle "do while" para leer la salida del comando find. En este ejemplo, estoy haciendo coincidir (en lugar de excluir) ciertos patrones, ya que hay un número más limitado de coincidencias de patrones que quiero que no quiero. Puede revertir la lógica con un -no delante de las banderas -iname:
Utilizo lo anterior para copiar todos los archivos de tipo de música que son más nuevos en mi servidor que los archivos en un Western Digital TV Live Hub que he montado en / media / wd. Utilizo lo anterior porque tengo muchos archivos DVD, mpegs, etc. que quiero excluir Y porque por alguna razón parece que rsync se está copiando, pero después de mirar el dispositivo wd, los archivos no están ahí a pesar de que no errores durante el rsync con este comando:
fuente
La primera parte
ls
todos los archivos pero archivos específicos ocultos con bandera-I
. La salida dels
se utiliza como entrada estándar para la segunda parte.xargs
construir y ejecutar comandoscp -rf -t destdir
desde la entrada estándar. la bandera-r
significa copiar directorios de forma recursiva,-f
significa copiar archivos a la fuerza que sobrescribirán los archivos endestdir
,-t
especifique la copia del directorio de destino.fuente
cp -r
ls -A | grep -v "Excluded_File_or_folder"
../$target_location -vfuente