Como usar comandos que solo trabajan con un archivo a la vez con todos los ficheros que selecciones

Muchas veces necesitamos ejecutar una secuencia de comandos ya sea para convertir un pdf en texto, convertir los ficheros .doc en html, etc; la cuestiรณn es que dichos comandos solo aceptan un fichero a la vez y eso nos resulta muy tedioso si necesitamos realizar la misma tarea a varios archivos sobre todo cuanto realizamos un script.

Yo les propongo una soluciรณn para este problema usando ls, sed, grep, awk y sh. Lo que haremos serรก crear la linea de comandos correcta en cada fila y ejecutarlas con sh, y como sh ejecutara una linea a la vez no se aumentara el consumo de memoria ram que con otros mรฉtodos pueden hasta congelar a las maquinas de poca potencia.

Veamos como realizar realizar dicha secuencia de comando.

1- Lo primero que tenemos que hacer sera introducir los ficheros que se usaran mediante ls:

ls --directory /camino/a/carpeta/*.ext

2- Luego necesitaremos que dichos ficheros pasen encomillados ยซ/camino/a grupo de
ficherosยซ

ls --directory /camino/a/carpeta/*.ext | sed 's/^/"/' | sed 's/$/"/'

3- Ahora awk estarรก listo para recibir los datos.

ls --directory /camino/a/carpeta/*.ext | sed 's/^/"/' | sed 's/$/"/' | awk '{print $0}'

Debido a que awk tiene su propio lenguaje necesitaremos separar las comillas que queramos que salgan para encomillar un texto entre otras funciones necesitaremos usar la barra invertida \ veamos como separar algunas.
Separar una comilla

\โ€

Mostrar una barra invertida en la salida (necesitaremos teclear tres barras)

\\\

Algunas veces necesitaremos un separador aislador, solo saldrรก en la salida el texto o las comillas que aparezcan dentro de las dos barras invertidas.:

'""'\"\'""'

4- Veamos como renombrar todos los ficheros que se listen usando el comando mv solamente para introducir un sufijo. (ahora para listar el fichero necesitaremos usarรก la combinaciรณn ยซ$0ยป siempre que necesitemos usarla)

ls --directory /camino/a/carpeta/*.ext | sed 's/^/"/' | sed 's/$/"/' | awk '{print "mv "$0" \"`dirname

ยซ$0โ€ณ`/Texto-cualquiera-`basename ยซ$0โ€ณ`\ยป ยซ}โ€™ | sh

Nota se le agrega al final como se muestra en la anterior secuencia la combinaciรณn ยซ | sh ยป que redirige la tuberรญa a este interprete de ordenes

Veamos algunos ejemplos preparados para crear un script.

Ejemplos:

1- Convertir todos los pdf que se listen en ficheros de texto.

ls --directory โ€œ$@โ€ | sed 's/^/"/' | sed 's/$/"/' | awk '{print "pdftotext",$0}' | sh

En este caso no es necesario seleccionar un fichero de salida puesto que pdftotext genera automรกticamente un fichero de texto con el nombre base y la exenciรณn .txt si y solo si se trabaja con un solo archivo.

2- Digamos que queremos aplicarle un efecto a una imagen pero sin modificar la original, veamos un ejemplo con el efecto wave muy conocido por el logotipo de Windows XP, pues se trata de una bandera con efectos oondulados (para apreciar mejor este efecto se recomienda usar como imagen resultante la extensiรณn .png).

ls --directory โ€œ$@โ€ | sed 's/^/"/' | sed 's/$/"/' | awk '{print FS="convert -wave 25x150

"$0"","\"\`dirname "$0"`/`basename "$0" | sed '"'"s/\\\\.[[:alnum:]]*$//"'"'`-wave.`basename "$0" |
rev | awk -F . \'"'"'\{print $1}\'"'"'\ | rev`'""'\"\'""' "}' | sh

Nota: en esta secuencia se realizan varias pasadas:

  • Una para obtener la carpeta donde se encuentra el fichero con dirname
  • Otra para obtener el nombre base, pero eliminando la extensiรณn de dicho fichero
  • Otra para obtener la exenciรณn de dicho fichero.

3- Veamos ahora como renombrar un grupo de ficheros poniรฉndole el nรบmero correspondiente delante del nombre (sufijo numรฉrico).

ls --directory โ€œ$@โ€ | sed 's/^/"/' | sed 's/$/"/' | awk '{print FS="mv "$0" '""'\"\'""'`dirname
"$0"`/"FNR"-`basename "$0"`'""'\"\'""' "}' | sh

Para ingresarle el nรบmero se uso el lenguaje interno de awk con la opciรณn โ€œFNRโ€ que enumera cada lรญnea de salida, por lo que el numero se puede poner adelante o detrรกs del texto.

Veamos como poner un prefijo nรบmerico (poner un nรบmero al final, pero antes de la exenciรณn) esta opciรณn solo es valida si el archivo tiene una extensiรณn.

ls --directory โ€œ$@โ€ | sed 's/^/"/' | sed 's/$/"/' | awk '{print FS="mv "$0" \"`dirname
"$0"`/`basename "$0" | sed '\'s/\\\\.[[:alnum:]]*$//\''`-"FNR".`echo "$0" | rev | awk -F .
'""'\'\'""'{print $1}'""'\'\'""' | rev `\" " }' | sh

4- Veamos un ejemplo donde tendremos que introducir datos o seleccionar un grupo de funciones tomando como ejemplo el caso donde le quitamos la protecciรณn por contraseรฑa a varios ficheros de pdf que tienen la misma clave. (En este caso usaremos zenity como caja de dialogo)

zenity --entry --hide-text --text "introduzca la clave de desbloqueo" > $HOME/.cat && ls
--directory โ€œ$@โ€ | sed 's/^/"/' | sed 's/$/"/' | awk '{print FS="pdftk "$0" input_pw `cat
$HOME/.cat` output \"`dirname "$0"`/`basename "$0" .pdf`-unlock.pdf\" "}' | sh && rm
$HOME/.cat

En dependencia de la versiรณn de zenity la opciรณn para el pasword puede ser solo โ€“pasword.

Como vieron el objetivo es hacer un cat de un fichero que se creara al principio de la linea una sola vez y luego sera eliminado una vez concluya la conversiรณn.

5- Otra utilidad es, cuando necesitamos descomprimir varios ficheros compactado en .zip

ls --directory โ€œ$@โ€ | sed 's/^/"/' | sed 's/$/"/' | awk '{print "unzip -x "$0" "}' | sh

Las comillas extras deberรกn separarse con un espacio donde se use la opciรณn ยซ$0ยป
Ejemplo
"unzip -x "$0" "

6- Veamos un ejemplo para proteger un pdf con contraseรฑa permitiendo la lectura pero protegido contra la copia impresiรณn u otras opciones, (las opciones que se listen en la caja de dialogo serรกn las que se permitirรกn en el pdf, si no quiere permitir ninguna de ellas no seleccione ninguna).

zenity --separator " " --multiple --text "Seleccione los Opciones que quiere permitir" --column "Opciones" --list "Printing" "DegradedPrinting" "ModifyContents" "CopyContents" "ScreenReaders" "ModifyAnnotations" "AllFeatures" > $HOME/.cat && zenity --entry --hidetext --text "Teclee la contraseรฑa de protecciรณn" > $HOME/.cat2 && ls --directory "$@" | sed 's/^/"/' | sed 's/$/"/' | awk '{print FS="echo \"pdftk \\\"`echo "$0"`\\\" output \\\"`dirname "$0"`/`basename "$0" .pdf`-locked.pdf\\\" allow `cat $HOME/.cat` owner_pw \"`cat $HOME/.cat2`\"\" | sh "}' | sh && rm $HOME/.cat $HOME/.cat2

Con estos ejemplos queda bastante ejemplificado como usar esta opciรณn para convertir, modificar o renombrar varios archivos con una sola secuencia de comandos y no convirtiรฉndolos a mano uno por uno. El consumo de memoria con esta opciรณn es mรญnimo, en dependencia del comando que se este usando, ya que no los convierte al mismo tiempo sino uno detrรกs del otro.

Esta opciรณn nos puede resultar muy util si deseamos convertir todo un grupo de videos con mencoder sin que este los una en uno solo; se puede preparar un script para esto y solo tendrรญan que poner ls --directory %F | sed 's/^/"/' | sed 's/$/"/' | awk '{print "script-convertir-video "$0" "}' | sh && zenity --info --text "Todas las conversiones han terminado"

FIN


Deja tu comentario

Tu direcciรณn de correo electrรณnico no serรก publicada. Los campos obligatorios estรกn marcados con *

*

*

  1. Responsable de los datos: Miguel รngel Gatรณn
  2. Finalidad de los datos: Controlar el SPAM, gestiรณn de comentarios.
  3. Legitimaciรณn: Tu consentimiento
  4. Comunicaciรณn de los datos: No se comunicarรกn los datos a terceros salvo por obligaciรณn legal.
  5. Almacenamiento de los datos: Base de datos alojada en Occentus Networks (UE)
  6. Derechos: En cualquier momento puedes limitar, recuperar y borrar tu informaciรณn.

      Ramiro dijo

    ยฟNo serรญa mucho, pero MUCHรSIMO mรกs facil hacer todo esto usando expresiones regulares o comodines? No entiendo cuรกl es la diferencia entre eso y complicarse tanto la vida con esto.

      croto dijo

    La verdad tahed, tenes gran conocimiento de los comandos de linux. Muy รบtil!

         KZKG^Gaara dijo

      Sรญ, sรฉ que aprenderemos mucho con รฉl por acรก hahaha.

      hexborg dijo

    Creo que esto es mucho mรกs facil:

    ls -d /camino/a/carpeta/*.ext | while read file; do COMANDO ยซ$fileยป; done

    En lugar de COMANDO puedes poner lo que quieras y funciona aunque los ficheros contengan espacios en blanco siempre que pongas $file entre comillas. No es necesario usar sed para eso ni generar los comandos con awk. Ademรกs esto lanza menos procesos.

         Ankh dijo

      o:
      for i in $(ls -d /camino/a/carpeta/*.ext); do COMANDO โ€œ$iโ€; done;

           hexborg dijo

        Eso tiene buena pinta, pero si los nombres de los ficheros contienen espacios en blanco no funciona. ๐Ÿ™‚

             tahed dijo

          De hecho hexborg por eso es que se encomilla el texto de salida al inicio y al final por cada linea con esta opciรณn:
          ls –directory | sed ‘s/^/ยป/’ | sed ‘s/$/ยป/’

          Aclaro que se puede usar find para que busque en los subdirectorios.

               hexborg dijo

            Pero con mi truco no hace falta. ls saca los nombres completos de los ficheros uno en cada linea y read lee linea a linea y deja el nombre del fichero en la variable file tanto si tiene espacios en blanco o no. Sรณlo hace falta poner comillas alrededor de $file al usarlo en el comando.

               Hugo dijo

            Estoy de acuerdo que en find puede ser menos engorroso. Tomemos este ejemplo del artรญculo:

            ls --directory โ€œ$@โ€ | sed 's/^/"/' | sed 's/$/"/' | awk '{print "pdftotext",$0}' | sh

            Bien podrรญa conseguirse lo mismo asรญ, y probablemente se ejecute mรกs rรกpido:

            find . -type f -print0 | xargs -0 pdftotext

            Dicho esto, el artรญculo es bienvenido, siempre es bueno conocer maneras alternativas de hacer algo.

             Ankh dijo

          Si te fijas las $i estรก entre comillas. Eso hace innecesario escapar los espacios en blanco.

               hexborg dijo

            Si, pero el operador $() expande los nombres de fichero sin poner comillas en ningรบn sitio, asรญ que la variable i ya pilla los nombres de los ficheros cortados. Pruรฉbalo en una terminal en un directorio que tenga ficheros con espacios en los nombres.

      Leo dijo

    Muy bueno, complejo, pero muy interesante.

      helena_ryuu dijo

    esto es alucinante, buenisimo!!!!

      msx dijo

    Excelente, la plasticidad de GNU/Linux no tiene lรญmites.

      Natalia dijo

    Estimado blogger,

    Soy Natalia, Responsable de Comunicaciรณn de Paperblog. Tras haberlo descubierto, me pongo en contacto contigo para invitarte a conocer el proyecto Paperblog, http://es.paperblog.com, un nuevo servicio de periodismo ciudadano. Paperblog es una plataforma digital que, a modo de revista de blogs, da a conocer los mejores artรญculos de los blogs inscritos.

    Si el concepto te interesa sรณlo tienes que proponer tu blog para participar. Los artรญculos estarรญan acompaรฑados de tu nombre/seudรณnimo y ficha de perfil, ademรกs de varios vรญnculos hacia el blog original, al principio y al final de cada uno. Los mรกs interesantes podrรกn ser seleccionados por el equipo para aparecer en Portada y tรบ podrรกs ser seleccionado como Autor del dรญa.

    Espero que te motive el proyecto que iniciamos con tanta ilusiรณn en enero de 2010. ร‰chale un ojo y no dudes en escribirme para conocer mรกs detalles.

    Recibe un cordial y afectuoso saludo,
    Natalia