¿Cómo puedo hacer una matriz de files específicos en un directory usando el command shell en Linux?

He intentado agregar files de less de 2 megabytes en un directory a una matriz y luego agregar esos files a git y luego confirmarlos.

find . -type f -size -2M i=0 while read line do array[ $i ]="$line" (( i++ )) done for item in "${array[@]}" do git add "$item" done git commit -am "${COMMIT_MESSAGE}" 

Se supone que el script agrega y confirma files por debajo de 2M. Pero mi script está agregando y confirmando todos los files (incluidos los que superan los 2 millones). ¿Qué estoy haciendo mal?

Forma abreviada: resolviendo el problema inmediato

Primero, con respecto a leer correctamente los files de find , siga los consejos en la respuesta de @ chepner .

Segundo, en cuanto a por qué su código existente incluye todos los files ya agregados a git en alguna revisión anterior, a diferencia de solo aquellos bajo 2MB, a pesar de no ejecutar git add en absoluto : Eso es porque está pasando el argumento -a a la git commit .

 find . -type f -size -2M -exec git add -- {} + git commit -m "Commit message" # no -a here! 

Forma larga: explicando el problema

Para ser claro en cuanto a lo que quiero decir con "a pesar de no ejecutar git add nada ", como se escribe actualmente, el resultado de find no se pasa al ciclo de while read while.

 find . while read ... 

no networkingirige la salida de find en el ciclo while read . Por lo tanto, su ciclo while read line itera solo en la input dada a su secuencia de commands en stdin, si hay alguna (y la salida de find está escrita en stdout).

Para otros asuntos, vea las notas a continuación.


Forma larga: respondiendo la pregunta como se le preguntó

Ahora, para responder a su pregunta literal sobre cómo build una matriz de shell, hacerlo bien se parece a lo siguiente:

 # correctly building a shell array files=( ) while IFS= read -r -d '' file; do files+=( "$file" ) done < <(find . -type f -size -2M -print0) ## using that array efficiently (if not huge) #git add -- "${files[@]}" # using that array efficiently (if potentially huge) printf '%s\0' "${files[@]}" | xargs -0 git add -- 

Notas de implementación:

  • Al colocar el bucle while en el shell externo, se garantiza que los cambios en el estado variable que hace sean accesibles una vez que finalice la ejecución. Es necesario usar el modismo < <(...) para hacerlo, como se indica en BashFAQ # 24 .
  • Pasar múltiples files a una sola instancia de git add es mucho más eficiente que llamar a git add una vez por file.
  • El uso del argumento -print0 para find hace que los nombres de los files estén separados por NUL (que, a diferencia de los literales de nueva línea, no pueden existir en los nombres de los files) en el resultado de find .
  • Usando la expresión de IFS= read -r -d '' file (como se describe en BashFAQ # 1 ) se leen nombres de find en byte por byte literal.
  • Utilizar array+=( "$value" ) es mucho, mucho más fácil que mantener un contador de índice integer e incrementarlo entre cada apéndice.

Use find para ejecutar git add .

 find . -type f -size -2M -exec git add {} + 

Esto funcionará para todos los nombres de file válidos.

La opción -a para commit probablemente no sea necesaria. Si solo tiene files grandes sin seguimiento, no se agregarán mediante commit -a todos modos, y ya habrá agregado todos los files pequeños modificados. Sin embargo, debe soltarlo si tiene grandes files rastreados con modificaciones que no desea include en la confirmación pendiente.

Por favor, inténtalo

 find . -type f -size -2M -print0 | xargs -0 git add git commit -m 'Message here' 

el command de una línea del primer comentario es bueno, pero si aún necesita un script para agregar algo de lógica adicional intente usar esto:

 #!/bin/bash root_dir="/home/myuser/myproject" exclude_path="dirname_to_exclude" max_size="-2048k" for file in $(find $root_dir -type f -size $max_size | grep -v $exclude_path) do git add $file done git commit -m "blablabla..."