Pagina inicial » como » O Guia do Iniciante ao Shell Scripting 2 For Loops

    O Guia do Iniciante ao Shell Scripting 2 For Loops

    Se você quiser criar credibilidade, junte-se a nós na segunda parte da nossa série de scripts de shell. Temos algumas correções, algumas melhorias no roteiro da semana passada e um guia sobre looping para os não iniciados..

    O script datecp revisitado

    Na primeira parte do nosso guia de script de shell, fizemos um script que copiou um arquivo para um diretório de backup após anexar a data ao final do nome do arquivo..

    Samuel Dionne-Riel apontou nos comentários que há uma maneira muito melhor de lidar com nossas referências variáveis.

    Os argumentos são separados por espaço no shell bash, ele será tokenizado quando houver um espaço no comando expandido resultante. Em seu script, cp $ 1 $ 2. $ date_formatted funcionará como pretendido, desde que as variáveis ​​expandidas não possuam espaços. Se você chamar seu script desta maneira: datecp "meu nome antigo" "meu novo nome" a expansão resultará neste comando: cp meu novo nome meu antigo nome.the_date que na verdade tem 6 argumentos.

    Para resolver esse problema corretamente, a última linha do script deve ser: cp "$ 1" "$ 2. $ date_formatted"

    Como você pode ver, alterando a linha do nosso script de:

    cp -iv $ 1 $ 2. $ date_formatted

    para:

    cp -iv "$ 1" "$ 2". $ date_formatted

    vai cuidar desse problema ao usar o script em arquivos que possuem espaços no nome. Samuel também argumenta que, ao copiar e colar o código deste site (ou da Internet em geral), certifique-se de substituir os traços e aspas apropriados pelos que são "tipograficamente melhores", que geralmente os substituem. Também faremos mais para garantir que nosso código seja mais compatível com copiar / colar. ;-)

    Outro comentarista, Myles Braithwaite, decidiu expandir nosso script para que a data aparecesse antes da extensão do arquivo. Então, ao invés de

    tastyfile.mp3.07_14_11-12.34.56

    nós conseguiríamos isso:

    tastyfile.07_14_11-12.34.56.mp3

    o que acaba sendo um pouco mais conveniente para a maioria dos usuários. Seu código está disponível em sua página do GitHub. Vamos dar uma olhada no que ele usa para separar o nome do arquivo.

    date_formatted = $ (date +% Y-% m-% d_% H.% M% S)
    file_extension = $ (echo “$ 1" | awk -F. 'print $ NF')
    file_name = $ (basename $ 1. $ file_extension)

    cp -iv $ 1 $ file_name- $ date_formatted. $ file_extension

    Eu mudei a formatação um pouco, mas você pode ver que Myles declara sua função de data na Linha 1. Na Linha 2, no entanto, ele usa o comando “echo” com o primeiro argumento do script para gerar o nome do arquivo. Ele usa o comando pipe para pegar essa saída e usá-la como entrada para a próxima parte. Depois do pipe, Myles chama o comando “awk”, que é um poderoso programa de varredura de padrões. Usando o sinalizador -F, ele está dizendo ao comando que o próximo caractere (depois de um espaço) é o que definirá o “separador de campo”. Neste caso, esse é um período.

    Agora, awk vê um arquivo chamado “tastyfile.mp3” como sendo composto de dois campos: “tastyfile” e “mp3”. Por fim, ele usa

    'print $ NF'

    para exibir o último campo. Caso o seu arquivo tenha vários períodos - portanto fazendo o awk ver vários campos - ele exibirá apenas o último, que é a extensão do arquivo..

    Na linha 3, ele cria uma nova variável para o nome do arquivo e usa o comando “basename” para fazer referência a tudo em $ 1 exceto a extensão do arquivo. Isso é feito usando o basename e dando a ele $ 1 como argumento, depois adicionando um espaço e a extensão do arquivo. A extensão do arquivo é automaticamente adicionada por causa da variável que faz referência à Linha 2. O que isso faria é

    tastyfile.mp3

    e transformá-lo em

    saboroso

    Então, na última linha, Myles reúne o comando que irá mostrar tudo em ordem. Note que não há referência a $ 2, um segundo argumento para o script. Este script em particular irá copiar o dito arquivo para o seu diretório atual. Grande trabalho Samuel e Myles!

    Executando Scripts e $ PATH

    Também mencionamos em nosso artigo Básico que os scripts não podem ser referenciados como comandos por padrão. Ou seja, você precisa apontar para o caminho do script para executá-lo:

    ./roteiro

    ~ / bin / script

    Mas, colocando seus scripts em ~ / bin /, você poderia simplesmente digitar seus nomes de qualquer lugar para executá-los.

    Os comentadores passaram algum tempo debatendo como isso era correto, já que nenhuma distro moderna do Linux cria esse diretório por padrão. Além disso, ninguém o adiciona à variável $ PATH por padrão, o que é necessário para que os scripts sejam executados como comandos. Fiquei um pouco confuso porque depois de verificar minha variável $ PATH, os comentaristas estavam certos, mas os scripts de chamada ainda funcionavam para mim. Descobri o porquê: muitas distros modernas do Linux criam um arquivo especial no diretório home do usuário - .profile.

    Esse arquivo é lido por bash (a menos que .bash_profile esteja presente no diretório pessoal do usuário) e na parte inferior há uma seção que adiciona o ~ / bin / folder à variável $ PATH, se existir. Então, esse mistério é esclarecido. Para o restante da série, continuarei colocando scripts no diretório ~ / bin / porque eles são scripts de usuário e devem poder ser executados por usuários. E parece que não precisamos mexer com a variável $ PATH manualmente para fazer as coisas funcionarem.

    Repetindo Comandos Com Loops

    Vamos chegar a uma das ferramentas mais úteis no arsenal geek para lidar com tarefas repetitivas: loops. Hoje, vamos discutir loops "para".

    O esboço básico de um loop for é o seguinte:

    para VARIÁVEL em LISTA; Faz
    comando1
    comando2

    comando
    feito

    VARIÁVEL pode ser qualquer variável, embora na maioria das vezes o minúsculo "i" seja usado por convenção. LIST é uma lista de itens; você pode especificar vários itens (separando-os por um espaço), apontar para um arquivo de texto externo ou usar um asterisco (*) para denotar qualquer arquivo no diretório atual. Os comandos listados são recuados por convenção, então é mais fácil ver aninhamento - colocando loops em loops (assim você pode fazer um loop enquanto faz um loop).

    Como as listas usam espaços como delimitadores - isto é, um espaço significa uma mudança para o próximo item na lista - os arquivos que possuem espaços no nome não são muito amigáveis. Por enquanto, vamos continuar trabalhando com arquivos sem espaços. Vamos começar com um script simples para exibir os nomes dos arquivos no diretório atual. Crie um novo script na sua pasta ~ / bin / intitulada “loopscript”. Se você não se lembrar de como fazer isso (incluindo marcá-lo como executável e adicionar o hack do hash), consulte nosso artigo sobre bash scripting bash.

    Nele, digite o seguinte código:

    para i no item1 item2 item3 item4 item5 item6; Faz
    eco "$ i"
    feito

    Quando você executa o script, você deve apenas obter esses itens da lista como saída.

    Bem simples, certo? Vamos ver o que acontece se mudarmos um pouco as coisas. Altere seu script para que ele diga isto:

    para i em *; Faz
    eco "$ i"
    feito

    Quando você executa este script em uma pasta, você deve obter uma lista de arquivos que ele contém como saída.

    Agora, vamos alterar o comando echo para algo mais útil - digamos, o comando zip. Ou seja, vamos adicionar arquivos em um arquivo. E, vamos pegar alguns argumentos no mix!

    para i em $ @; Faz
    arquivo zip "$ i"
    feito

    Há algo novo! "$ @" É um atalho para "$ 1 $ 2 $ 3… $ n". Em outras palavras, é a lista completa de todos os argumentos que você especificou. Agora, observe o que acontece quando eu executo o script com vários arquivos de entrada.

    Você pode ver quais arquivos estão na minha pasta. Eu corri o comando com seis argumentos, e cada arquivo foi adicionado a um arquivo compactado chamado "archive.zip". Fácil, certo?

    For loops são maravilhosos. Agora você pode executar funções em lote nas listas de arquivos. Por exemplo, você pode copiar todos os argumentos do seu script em um arquivo compactado, mover os originais para uma pasta diferente e proteger automaticamente a cópia desse arquivo zip para um computador remoto. Se você configurar arquivos de chave com SSH, nem precisará inserir sua senha, e poderá até mesmo instruir o script a excluir o arquivo zip após carregá-lo.!


    O uso de loops for-lo facilita a realização de várias ações para todos os arquivos em um diretório. Você pode empilhar uma grande variedade de comandos juntos e usar argumentos muito facilmente para criar uma lista dinâmica, e esta é apenas a ponta do iceberg..

    Bash scripters, você tem alguma sugestão? Você fez um script útil que usa loops? Quer compartilhar seus pensamentos sobre a série? Deixe alguns comentários e ajude outros novatos a criar scripts!