Como usar comandos que só funcionan cun ficheiro á vez con todos os ficheiros que selecciona

Moitas veces necesitamos executar un script para converter un pdf en texto, converter os ficheiros .doc en html, etc; a cuestión é que estes comandos só aceptan un ficheiro á vez e iso é moi tedioso para nós se necesitamos realizar a mesma tarefa en varios ficheiros, especialmente cando facemos un script.

Propoño unha solución para este problema usando ls, sed, grep, vaia y sh. O que faremos é crear a liña de comandos correcta en cada fila e executalas con sh, e dado que sh executará unha liña á vez, o consumo de memoria RAM non aumentará, o que con outros métodos pode incluso conxelar máquinas con pouca potencia.

Vexamos como levar a cabo esta secuencia de comandos.

1- O primeiro que temos que facer é presentar os ficheiros que se empregarán ls:

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

2- Despois necesitaremos estes ficheiros para pasar comiñas «/ camiño / ao grupo de
arquivos«

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

3- Agora vaia estará listo para recibir os datos.

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

Porque vaia ten a súa propia lingua teremos que separar as comiñas que queremos que aparezan para citar un texto entre outras funcións teremos que empregar a barra invertida \ Vexamos como separar algúns.
Separe unha cotización

\”

Mostrar unha barra invertida na saída (teremos que escribir tres barras)

\\\

Ás veces necesitaremos un separador illante, só sairá na saída o texto ou as comiñas que aparecen dentro das dúas barras invertidas:

'""'\"\'""'

4- Vexamos como renomear todos os ficheiros listados usando o comando mv só para introducir un sufixo. (Agora para listar o ficheiro teremos que empregar a combinación "$ 0" sempre que o necesitemos)

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

"$ 0 ″" / Text-any-`basename "$ 0 ″" \ ""} '| sh

A nota engádese ao final como se mostra na secuencia anterior a combinación « | sh »Que redirecciona a canalización a este intérprete de comandos

Vexamos algúns exemplos preparados para crear un script.

Exemplos:

1- Converte todos os pdf que se listan en ficheiros de texto.

ls --directory “$@” | sed 's/^/"/' | sed 's/$/"/' | awk '{print "pdftotext",$0}' | sh

Neste caso non é necesario seleccionar un ficheiro de saída xa que pdftotext xera automaticamente un ficheiro de texto co nome base e a exención .txt se e só se está a traballar cun só ficheiro.

2- Digamos que queremos aplicar un efecto a unha imaxe pero sen modificar o orixinal, vexamos un exemplo co efecto de onda ben coñecido polo logotipo de Windows XP, xa que é unha bandeira con efectos ondulados (para mellor apreciar este efecto é recoméndase usar como imaxe resultante coa 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: fanse varios pases nesta secuencia:

  • Un para obter o cartafol onde se atopa o ficheiro con dirname
  • Outro para obter o nome base, pero eliminando a extensión do devandito ficheiro
  • Outro para obter a exención de dito expediente.

3- Vexamos agora como renomear un grupo de ficheiros poñendo o número correspondente diante do nome (sufixo numérico).

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

Para introducir o número, empregouse o idioma awk interno coa opción "FNR" que lista cada liña de saída, polo que o número pode colocarse antes ou despois do texto.

Vexamos como poñer un prefixo numérico (poña un número ao final, pero antes da exención) esta opción só é válida se o ficheiro ten un.

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- Vexamos un exemplo no que teremos que introducir datos ou seleccionar un grupo de funcións, tomando como exemplo o caso no que eliminamos a protección por contrasinal de varios ficheiros pdf que teñen o mesmo contrasinal. (Neste caso usaremos zenity como un cadro de diálogo)

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

Dependendo da versión de zenity a opción para o contrasinal pode ser só –pasword.

Como viches, o obxectivo é facer un gato dun ficheiro que se creará ao comezo da liña só unha vez e que se eliminará unha vez finalizada a conversión.

5- Outra utilidade é cando necesitamos descomprimir varios ficheiros compactados en .zip

ls --directory “$@” | sed 's/^/"/' | sed 's/$/"/' | awk '{print "unzip -x "$0" "}' | sh

As comiñas adicionais deben separarse cun espazo onde se use a opción "$ 0"
Exemplo
"unzip -x "$0" "

6- Vexamos un exemplo para protexer un pdf cun contrasinal, permitindo a lectura pero protexido contra a impresión de copias ou outras opcións (as opcións listadas no cadro de diálogo serán as que se permitirán no pdf, se non quere permitir ningunha deles, non seleccione ningún).

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 estes exemplos exemplifícase bastante como usar esta opción para converter, modificar ou renomear varios ficheiros cun único script e non convertelos manualmente un por un. O consumo de memoria con esta opción é mínimo, dependendo do comando que se estea a usar, xa que non os converte ao mesmo tempo senón un tras outro.

Esta opción pode ser moi útil se queremos converter todo un grupo de vídeos con mencoder sen que este os xunte nun só; podes preparar un guión para iso e só terían que poñer ls --directory %F | sed 's/^/"/' | sed 's/$/"/' | awk '{print "script-convertir-video "$0" "}' | sh && zenity --info --text "Todas las conversiones han terminado"

FIN


O contido do artigo adhírese aos nosos principios de ética editorial. Para informar dun erro faga clic en aquí.

15 comentarios, deixa os teus

Deixa o teu comentario

Enderezo de correo electrónico non será publicado. Os campos obrigatorios están marcados con *

*

*

  1. Responsable dos datos: Miguel Ángel Gatón
  2. Finalidade dos datos: controlar SPAM, xestión de comentarios.
  3. Lexitimación: o seu consentimento
  4. Comunicación dos datos: os datos non serán comunicados a terceiros salvo obrigación legal.
  5. Almacenamento de datos: base de datos aloxada por Occentus Networks (UE)
  6. Dereitos: en calquera momento pode limitar, recuperar e eliminar a súa información.

  1.   ramiro dixo

    Non sería moito, pero MOITO máis doado facer todo isto usando expresións regulares ou comodíns? Non entendo cal é a diferenza entre iso e complicar a túa vida con isto.

  2.   Croto dixo

    A verdade, ten un gran coñecemento dos comandos Linux. Moi útil!

    1.    KZKG ^ Gaara dixo

      Si, sei que aprenderemos moito con el por aquí jajaja.

  3.   hexborg dixo

    Creo que isto é moito máis doado:

    ls -d /path/to/folder/*.ext | mentres se le o ficheiro; facer COMANDO "$ ficheiro"; feito

    En lugar de COMMAND podes poñer o que queiras e funciona aínda que os ficheiros conteñan espazos en branco sempre que poñas $ file entre comiñas. Non precisa usar sed para iso nin xerar os comandos con awk. Tamén lanza menos procesos.

    1.    Ankh dixo

      o:
      para i en $ (ls -d /path/a/folder/*.ext); fai COMANDO "$ i"; feito;

      1.    hexborg dixo

        Parece bo, pero se os nomes dos ficheiros conteñen espazos en branco, non funciona. 🙂

        1.    tahed dixo

          De feito, hexborg é por iso que o texto de saída cítase ao principio e ao final para cada liña con esta opción:
          ls –directorio | sed 's / ^ / »/' | sed 's / $ / »/'

          Aclaro que o find pode usarse para buscar nos subdirectorios.

          1.    hexborg dixo

            Pero co meu truco non fai falta. Ls leva os nomes completos dos ficheiros un en cada liña e le le liña por liña e deixa o nome do ficheiro na variable do ficheiro, teña ou non espazos en branco. Só precisa poñer comiñas ao redor de $ file ao usalo no comando.

          2.    Hugo dixo

            Estou de acordo en que atopalo pode ser menos engorroso. Tomemos este exemplo do artigo:

            ls --directory “$@” | sed 's/^/"/' | sed 's/$/"/' | awk '{print "pdftotext",$0}' | sh

            Poderíase facer o mesmo así e probablemente funcionará máis rápido:

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

            Dito isto, o artigo é benvido, sempre é bo aprender sobre formas alternativas de facer algo.

        2.    Ankh dixo

          Se notas que o $ i está entre comiñas. Iso fai innecesario escapar do espazo en branco.

          1.    hexborg dixo

            Si, pero o operador $ () amplía os nomes dos ficheiros sen poñer comiñas en ningures, polo que a variable i xa colle os nomes dos ficheiros cortados. Próbao nun terminal dun directorio que conteña ficheiros con espazos nos nomes.

  4.   León dixo

    Moi bo, complexo, pero moi interesante.

  5.   helena_ryuu dixo

    isto é incrible, estupendo !!!!

  6.   MSX dixo

    Excelente, a plasticidade de GNU / Linux non ten límites.

  7.   Natalia dixo

    Estimado blogueiro,

    Son Natalia, Xerente de Comunicacións de Paperblog. Despois de descubrilo, estou a poñerme en contacto contigo para convidarte a coñecer o proxecto Paperblog, http://es.paperblog.com, un novo servizo de xornalismo cidadán. Paperblog é unha plataforma dixital que, como unha revista de blogs, publica os mellores artigos dos blogs rexistrados.

    Se o concepto che interesa, só tes que propoñer o teu blog para participar. Os artigos irían acompañados do seu nome / pseudónimo e ficheiro de perfil, así como de varias ligazóns ao blog orixinal, ao comezo e ao final de cada un. Os máis interesantes poden ser seleccionados polo equipo para que aparezan na Portada e pode ser seleccionado como Autor do día.

    Espero que estea motivado polo proxecto que comezamos con tal entusiasmo en xaneiro de 2010. Bota unha ollada e non dubide en escribirme para máis detalles.

    Reciba un cordial e agarimoso saúdo,
    Natalia