¿Cómo se utilizan expresiones regulares con el comando cp en Linux?


22

Estoy tratando de copiar solo un subconjunto de archivos de un directorio a otro usando, cpsin embargo, me recibe el mensaje cp: cannot stat [^\.php]': No such file or directory. ¿Hay alguna manera de usar expresiones regulares solo usando el cpcomando?

Respuestas:


29

No.

El cpcomando no posee la capacidad de procesar ninguno de sus argumentos como expresiones regulares. Incluso los comodines no son manejados por él (o la mayoría de los ejecutables); más bien son manejados por el caparazón.

cp test/* test2/en realidad se expande con bash, y todo lo que cprealmente ve por sus argumentos es cp test/file1 test/file2 test/file3 test2/(o lo que sea apropiado en función del contenido real de test/).

Además, no creo que su expresión [^\.php]coincida con lo que desea (no coincide solo con los archivos que contienen .php).

Probablemente desee examinar la findutilidad para filtrar una lista de archivos basada en la expresión regular, y luego usarla xargspara aplicar la lista de archivos devueltos al cpcomando (suponiendo que find no tiene un controlador incorporado para copiar archivos; I ' No estoy íntimamente familiarizado con la herramienta).

Puedes probar:

find . ! -iregex ".*\.php.*" -exec cp {} /destination/folder/ \;

Esto dice que busque en el directorio actual de forma recursiva archivos que no contengan ".php" en la ruta y los copie /destination/folder/.

Según lo solicitado, un desglose más específico de los argumentos:

  • . - Ubicación para comenzar la búsqueda - en este caso, el directorio actual
  • ! - Operador "No", invierta el resultado de la próxima prueba
  • -iregex- Prueba de expresión regular sin distinción entre mayúsculas y minúsculas. El siguiente argumento es la expresión.
  • ".*\.php.*"- Coincidencia de expresiones regulares <Anything>.php<Anything>: cualquier archivo que tenga ".php" en algún lugar de la ruta. (Tenga en cuenta que, al estar dentro de una carpeta que contiene ".php" en el nombre, necesitaría una expresión más compleja para que solo coincida con los archivos)
  • -exec- Ejecute un comando si las pruebas anteriores devuelven verdadero. El siguiente argumento es el comando, todos los argumentos restantes hasta ;se pasan al comando. El {}es un argumento especial que representa el nombre del archivo.
  • cp - El comando que find` debe ejecutarse en cada uno de los nombres de ruta coincidentes.
  • {}- La ruta al archivo que se encontró, pasada cpcomo argumento para que sepa qué archivo copiar
  • /destination/folder/- argumento pasado a cp, indicando cpdónde debe copiar el archivo.
  • \;- Este es el ;terminador que -execestá buscando. Lo escapamos con un \para que su shell no intente analizarlo y en su lugar lo alimente como un argumento para el comando ( find)

Es bastante difícil escribir una expresión regular que coincida con "cadenas que no tienen .php", por lo que le pedimos findque busque cadenas que contengan .phpy luego invierta los resultados !.


2
find . -name [^\.php] -exec cp {} /path/to/location \;Tenga cuidado con los archivos con caracteres especiales.
Rob

@Darth Android: gracias. No sabía que cpotros binarios no podían expandir las expresiones regulares. ¿Te importaría explicar qué significan cada una de las opciones y argumentos en el ejemplo de ejemplo que diste? Sé que .se refiere al directorio actual, pero ¿qué !, {}, \;, etc refiero como bien lo que significan? Por ejemplo, ¿por qué tienes que escapar del ;?
PeanutsMonkey

@Rob - ¿Qué quieres decir con archivos especiales?
PeanutsMonkey

@Rob: intenté una expresión similar para eliminar archivos específicos, sin embargo, terminó eliminando todos los archivos del directorio. Mi orden era, find . -name '[^\.txt]' -exec rm {} \;por lo tanto, mi renuencia a usar find. Probablemente fue un error de mi parte, pero no estoy seguro de lo que hice mal. En lo que a mi entender se {}refiere a cada archivo encontrado por el comandofind . -name '[^\.txt]'
PeanutsMonkey

¿Qué intentas combinar con la expresión regular?
Rob

10

Puede usar algunas otras herramientas de la consola, como grep y xargs.

ls -1 some_folder | egrep 'some_extended_regex' | xargs cp -t destination_folder

¿Cómo es {}diferente a la de -t?
PeanutsMonkey

2
No mucho en este caso. La sintaxis alternativa para xargs sería 'xargs cp {} destination_folder'. la sintaxis estándar de cp toma una o varias fuentes y un destino al final, cuando usa la opción -t, puede especificar el destino después de -t, luego usa el resto de la línea para las fuentes. Solo encuentro la opción -t más conveniente en este caso. En el otro ejemplo, {} se reemplaza por lo que se canaliza a xargs (stdin), en este caso, el nombre del archivo.
0xAF

-1

Puede ejecutar el siguiente comando fácil de usar:

find /home/usr/search_dir -iname *file_name_portion*.txt | xargs cp -t /home/usr/destination_folder

guay haa !!

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.