Estoy intentando cambiar el nombre de todos los archivos que comienzan con "m" para que tengan el mismo nombre, excepto que se ha eliminado el primer carácter (o "m" en este caso).
Mi estrategia es:
- Enumere todos los archivos, con
ls
- Filtrar por los que quiero, con
egrep
- Generar la cadena que no quiero al lado de la que quiero, separada por un espacio, con
awk
, por ejemplo,mfoo foo
- alimentar
xargs
amv mfoo foo
Algunas preguntas:
- ¿Es esta una buena estrategia?
- ¿Cuál es mejor?
Estoy atascado en el Paso 3. A continuación se muestra cómo abordé el problema.
Estoy trabajando en el siguiente directorio:
$ find .
.
./cat
./mbar
./mbaz
./mfoo
Puedo obtener rápidamente 1-2:
$ ls | egrep '^m'
mbar
mbaz
mfoo
El paso 3 es más difícil. Solía gsub
generar la segunda cadena que quiero, pero no estoy seguro de cómo "pegarla con el valor original separado por un espacio":
$ ls | egrep '^m' | awk '{ gsub(/^./, ""); print }'
bar
baz
foo
El paso 4 tiene sentido para mí, aunque no estoy seguro de cómo terminar el paso 3, así que no puedo terminarlo todavía. A continuación se muestra un ejemplo de cómo creo que debería funcionar:
$ echo mfoo foo | xargs mv
$ find .
.
./cat
./foo
./mbar
./mbaz
Creo que estoy cerca. Sólo necesito descubrir cómo guardar el valor anterior e imprimirlo junto al valor gsubed. Probé el siguiente pequeño ejemplo pero no funciona:
$ echo mfoo | awk '
pipe quote> { old = $0 }
pipe quote> { new = gsub(/^./, "") }
pipe quote> { print $old " " $new }'
awk: illegal field $(mfoo), name "old"
input record number 1, file
source line number 4
- ¿Cómo hago una sustitución
$0
pero guardo el valor anterior? - ¿Por qué recibo este error?
Respuesta1
Esto debería manejar toda la operación:
for file in m*; do mv "${file}" "${file#m}"; done
Antes de ejecutar eso, verifique las cosas primero con
for file in m*; do echo mv "${file}" "${file#m}"; done
Esto usa el m*
glob para los pasos 1 y 2, luego ${file#m}
(que elimina “m” del principio de ${file}
) para el paso 3 y finalmente un bucle para el paso 4.
Para responder a su pregunta de AWK, puede hacerlo de esta manera:
echo mfoo | awk '{ print $0, substr($0, 2) }'
Las variables AWK no usan $
, eso es solo para campos; de ahí viene tu error: AWK entiende $old
como “el valor del campo numerado según el valor de old
”. También es más fácil de leer si colocas tus comandos en un solo bloque (suponiendo que tengan el mismo patrón). Arreglar tu guión te da
echo mfoo | awk '{ old = $0; gsub(/^./, ""); print old, $0 }'
Respuesta2
ls | egrep '^m' | awk '{ x=$0; gsub(/^./, ""); $0 = x " " $0 }1' | xargs -l -t mv
Posix-lyLa implementación se realiza a través de la -L
opción xargs
como:
ls | egrep '^m' | awk '{ x=$0; gsub(/^./, ""); $0 = x " " $0 }1' | xargs -L 1 -t mv
ls | egrep '^m' | awk '{ x=$0; gsub(/^./, ""); print x, $0 }' | xargs -L 1 -t mv
Basado en querespondíA su consulta anterior sobre xargs
, podemos darle un buen uso a ese aprendizaje en este ejemplo.
Modifiqué ligeramente su awk
código: conserva la línea original ( $0
) ya que la gsub
función la golpeará. Luego juntamos lo antiguo y lo nuevo para obtener la línea que queremos enviar a xargs
la que luego se invocará mv
con los argumentos correctos para efectuar el cambio de nombre.
Respuesta3
Una mejor estrategia es utilizar el rename
comando.
Tenga en cuenta que la sintaxis exacta de estos comandos es específica de la distribución; consulte la man
página de su versión particular de la distribución. En Ubuntu, por ejemplo, que tiene una implementación de Perl rename
, puedes usar una expresión regular:
rename -nono 's/^m//' m*
Nota: elimine la -nono
bandera para realizar el cambio de nombre.