Ejecutar una función Bash para cada archivo encontrado con el comando buscar

Ejecutar una función Bash para cada archivo encontrado con el comando buscar

Actualmente tengo este comando, que imprime con éxito cada nombre de archivo en su propia línea:

find . -exec echo {} \;

Estoy intentando dividir la lógica para que el findcomando ejecute una función. Residencia enesta preguntaHe probado esto:

my_function() {
    echo $1
}
export -f my_function
find . -exec bash -c 'my_function "$@"' bash {} +

Entonces obtengo este resultado:

.

También intenté reemplazar $@con $*, pero esto hace $1que todos los archivos no tengan saltos de línea. Me gustaría ejecutar una lógica que verifique cada archivo, por lo que me gustaría $1ser solo un archivo a la vez. Intenté dividir la salida con espacios for file in $1pero esto no funciona para archivos que tienen espacios en el nombre del archivo. ¿Cómo ejecuto una función Bash para cada archivo encontrado por el findcomando?

EDITAR: Aquí está el script completo que estoy usando. Parece que funciona bien.

# Ensures that non-csproj text files are formatted with LF line endings.
format() {
    for pathname do
        if [[ $pathname == *"git"* ]]; then
            continue
        elif [[ $pathname == *"csproj"* ]]; then
            continue
        fi
        dos2unix $pathname
    done
}
export -f format
find . -exec bash -c 'format "$@"' bash {} \;

Respuesta1

Para ejecutar dos2unix --newlineen todos los archivos normales dentro y debajo del directorio actual, evitando cualquier archivo cuyo nombre contenga la cadena git:

find . -type f ! -name '*git*' -exec dos2unix --newline {} +

Es decir, busque todos los archivos normales cuyos nombres no coincidan con el patrón *git*y ejecútelos dos2unix --newlinetodos en lotes tan grandes como sea posible a la vez. Cambie ! -name '*git*'a ! -path '*git*'para evitar cualquier archivo cuyo nombre de ruta contenga la cadena git(por ejemplo, archivos en .gitdirectorios).

Para evitar explícitamente cualquier .gitdirectorio, pero incluir cualquier otra cosa que pueda tener giten su nombre:

find . -name .git -prune -o -type f -exec dos2unix --newline {} +

Esto impide findincluso ingresar a cualquier directorio llamado .gitmediante el uso -prunepara eliminar dichas rutas del árbol de búsqueda.


Responda antes de editar la pregunta:

Su función imprime solo su primer argumento. El punto es la ruta de búsqueda de nivel superior que utiliza con find. Se pasa porque no realiza ningún filtrado particular de las entradas del directorio (como, por ejemplo, -type fsolo para archivos normales, -nameo cualquier otro tipo de findprueba).

Si desea que su función imprima cada uno de sus argumentos, utilice cualquiera de los dos

my_function() {
    printf '%s\n' "$@"
}

que permite printfimprimir cada uno de los argumentos con una nueva línea en el medio, o

my_function() {
    for pathname do
        printf '%s\n' "$pathname"
    done
}

que recorre los argumentos y llama printfuna vez para cada uno.

Se esperaría que esto funcionara correctamente si llamara a la función como

my_function "$@"

desde dentro de su secuencia de comandos en línea bash -c. Se "$@"amplía a todos los argumentos dados al guión, citados individualmente.

Otra forma sería mover el bucle al bash -cscript:

for pathname do
    my_function "$pathname"
done

y luego tener

my_function () {
    printf '%s\n' "$1"
}

Esto sería hacer explícitamente lo que usted dice que desea hacer, es decir, llamar a la función una vez para cada nombre de ruta.

El findcomando entonces se vería así

find . -exec bash -c 'for pathname do my_function "$pathname"; done' bash {} +

o, posiblemente, un poco más legible,

find . -exec bash -c '
    for pathname do
        my_function "$pathname"
    done' bash {} +

Por cierto, esto sería lo mismo que

shopt -s globstar nullglob dotglob

for pathname in ./**/*; do
    my_function "$pathname"
done

excepto que .no sería procesado. Al usar esto, no tendría que exportar su my_functionfunción.

Con el bucle dentro de la función (como en los dos primeros fragmentos de código de esta respuesta), esto se reduciría a

shopt -s globstar nullglob dotglob

my_function ./**/*

información relacionada