Lo siguiente debería funcionar absolutamente en cualquier ruta.
Declarar una función para poder usar head
y tail
en salida separada por NUL:
nul_terminated() {
tr '\0\n' '\n\0' | "[email protected]" | tr '\0\n' '\n\0'
}
Luego puede usarlo para obtener una lista de rutas separadas por NUL de su búsqueda después de pasar por tail
:
find . -exec printf '%s\0' {} \; | nul_terminated tail -n 2
Luego puede canalizar eso a xargs
y agrega tus opciones:
find . -iname "*FooBar*" -exec printf '%s\0' {} \; | nul_terminated tail -n 2 | xargs -I "{}" -0 cp "{}" "dest"
Explicación:
find
archivos en el directorio actual (.
) e inferiores con un nombre que contengafoobar
(no distingue entre mayúsculas y minúsculas debido ali
en-iname
);- para cada archivo, ejecute (
-exec
) un comando para - imprime la ruta de cada archivo (
{}
) seguido de un carácter NUL (\0
) individualmente (\;
); - intercambiar líneas nuevas y caracteres NUL (
tr '\0\n' '\n\0'
);" - obtener las dos últimas líneas (es decir, rutas;
tail -n 2
,"[email protected]"
); - cambie las líneas nuevas y los caracteres NUL nuevamente para obtener una lista de nombres de archivos separados por NUL (
tr '\0\n' '\n\0'
).
El xargs
El comando es un poco más difícil de explicar. Construye tantos cp ... "dest"
comandos según sea necesario para ajustarse a la longitud máxima del comando del sistema operativo, reemplazando el {}
token en el comando con el nombre de archivo real (-I "{}" ... "{}"
), utilizando el carácter NUL como separador al leer los parámetros (-0
).
Puedes probar
cp $(find . -iname "*FooBar*" | tail -2 ) dest
find . -iname "*FooBar*"|tail -n2|xargs -i cp "{}" dest
Lamentablemente, esto no funcionará con nombres de archivo que contengan espacios o saltos de línea.