bash - ¿Cómo ejecutar varios comandos después de xargs-0?
xargs grep (8)
find . -name "filename including space" -print0 | xargs -0 ls -aldF > log.txt
find . -name "filename including space" -print0 | xargs -0 rm -rdf
¿Es posible combinar estos dos comandos en uno para que solo se realice 1 búsqueda en lugar de 2?
Sé que para xargs: puede haber formas de hacerlo, lo que puede dar lugar a errores al proceder con los nombres de archivos, incluidos los espacios. Cualquier orientación es muy apreciada.
Creo que todas estas respuestas ya han dado las formas correctas para solucionar este problema. Y probé las 2 soluciones de Jonathan y el modo de Glenn, todo lo cual funcionó muy bien en mi Mac OS X. El método de mouviciel no funcionó en mi sistema operativo tal vez debido a algunas razones de configuración. Y creo que es similar al segundo método de Jonathan (puedo estar equivocado).
Como se menciona en los comentarios al método de Glenn, se necesita un pequeño ajuste. Así que aquí está el comando que probé que funcionó perfectamente para tu información:
find . -name "filename including space" -print0 |
xargs -0 -I ''{}'' sh -c ''ls -aldF {} | tee -a log.txt ; rm -rdf {}''
O mejor como lo sugiere Glenn:
find . -name "filename including space" -print0 |
xargs -0 -I ''{}'' sh -c ''ls -aldF {} >> log.txt ; rm -rdf {}''
Llego tarde a la fiesta, pero hay una solución más que no se trató aquí: funciones definidas por el usuario. Poner varias instrucciones en una línea es difícil de manejar y puede ser difícil de leer / mantener. El bucle for anterior evita eso, pero existe la posibilidad de exceder la longitud de la línea de comando.
Aquí hay otra manera (sin probar).
function processFiles {
ls -aldF "$@"
rm -rdf "$@"
}
export -f processFiles
find . -name "filename including space"` -print0 /
| xargs -0 bash -c processFiles dummyArg > log.txt
Esto es bastante sencillo, excepto por el "dummyArg" que me causó mucho dolor. Cuando se ejecuta bash de esta manera, los argumentos se leen en
"$0" "$1" "$2" ....
en lugar de lo esperado
"$1" "$2" "$3" ....
Como processFiles {} está esperando que el primer argumento sea " $ 1 ", tenemos que insertar un valor ficticio en " $ 0" .
Footnontes:
- Estoy usando algunos elementos de la sintaxis de bash (por ejemplo, " export -f "), pero creo que esto se adaptará a otros shells.
- La primera vez que intenté esto, no agregué un argumento ficticio. En su lugar, agregué " $ 0 " a las líneas de argumento dentro de mi función (por ejemplo, ls -aldf "$ 0" "$ @" ). Mala idea. Aparte de los problemas estilísticos, se rompe cuando el comando " encontrar " no devuelve nada. En ese caso, $ 0 se establece en "bash". En su lugar, el uso del argumento ficticio evita todo esto.
Mientras no tenga una nueva línea en sus nombres de archivo, no necesita -print0 para GNU Parallel:
find . -name "My brother''s 12/" records" | parallel ls {}/; rm -rdf {} >log.txt
Mire el video de introducción para obtener más información: http://www.youtube.com/watch?v=OpaiGYxkSuQ
Otra solución:
find . -name "filename including space" -print0 /
| xargs -0 -I FOUND echo "$(ls -aldF FOUND > log.txt ; rm -rdf FOUND)"
Puede ejecutar varios comandos después de find
utilizando for
lugar de xargs
:
IFS=$''/n''
for F in `find . -name "filename including space"`
do
ls -aldF $F > log.txt
rm -rdf $F
done
El IFS
define el Separador de campo interno, que por defecto es <space><tab> <newline>. Si sus nombres de archivo pueden contener espacios, es mejor redefinirlos como se indicó anteriormente.
Si solo desea evitar realizar la find
varias veces, puede hacer un tee
justo después de la find
, guardando la salida de la find
en un archivo y luego ejecutando las líneas como:
find . -name "filename including space" -print0 | tee my_teed_file | xargs -0 ls -aldF > log.txt
cat my_teed_file | xargs -0 rm -rdf
Otra forma de lograr esta misma cosa (si es que es lo que quieres lograr), es almacenar la salida del find
en una variable (suponiendo que no sea TB de datos):
founddata=`find . -name "filename including space" -print0`
echo "$founddata" | xargs -0 ls -aldF > log.txt
echo "$founddata" | xargs -0 rm -rdf
Solo una variación del enfoque de -print0
sin ese horrible -print0
y -print0
xargs -0
, así es como lo haría:
ls -1 *.txt | xargs --delimiter "/n" --max-args 1 --replace={} sh -c ''cat {}; echo "/n"''
Notas al pie:
- Sí, sé que las nuevas líneas pueden aparecer en los nombres de archivo, pero que en su sano juicio harían eso
- Hay opciones cortas para
xargs
pero para la comprensión del lector, he usado las largas. -
find -maxdepth 1 -iname "*.txt"
ls -1
cuando quiero un comportamiento no recursivo en lugar defind -maxdepth 1 -iname "*.txt"
que es un poco más detallado.
find . -name "filename including space" -print0 |
xargs -0 -I ''{}'' sh -c ''ls -aldF {} >> log.txt; rm -rdf {}''