O guia para iniciantes do Shell Scripting 2: For Loops

Índice:

O guia para iniciantes do Shell Scripting 2: For Loops
O guia para iniciantes do Shell Scripting 2: For Loops

Vídeo: O guia para iniciantes do Shell Scripting 2: For Loops

Vídeo: O guia para iniciantes do Shell Scripting 2: For Loops
Vídeo: DESEMBAÇAR OS VIDROS COM AR QUENTE OU FRIO? - YouTube 2024, Abril
Anonim
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.
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.

Arguments are space-separated in the bash shell, it will tokenize when there is a space in the resulted expanded command. In your 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 'my old name' 'my new name'

a expansão resultará neste comando:

cp my new name my old name.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), não se esqueça 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

Alterei um pouco a formatação, 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". Nesse 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 US $ 1 exceto a extensão do arquivo. Isso é feito usando o basename e dando a ele $ 1 como argumento, 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

tastyfile

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. Ótimo 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:

./script

~/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 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 inicial do usuário -.profile.

Esse arquivo é lido por bash (a menos que.bash profile esteja presente no diretório inicial do usuário) e, na parte inferior, há uma seção que adiciona a pasta ~ / bin / à variável $ PATH, se existir. Então, esse mistério é esclarecido. Para o restante da série, continuarei colocando scripts no diretório ~ / bin /, pois eles são scripts de usuário e devem poder ser executados pelos usuários. E parece que não precisamos mexer com a variável $ PATH manualmente para fazer as coisas funcionarem.
Esse arquivo é lido por bash (a menos que.bash profile esteja presente no diretório inicial do usuário) e, na parte inferior, há uma seção que adiciona a pasta ~ / bin / à variável $ PATH, se existir. Então, esse mistério é esclarecido. Para o restante da série, continuarei colocando scripts no diretório ~ / bin /, pois eles são scripts de usuário e devem poder ser executados pelos 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, discutiremos "por" loops.

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

for VARIABLE in LIST; do command1 command2 … commandn done

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, por isso é mais fácil ver aninhamento - colocando loops em loops (para que você possa fazer loop enquanto faz loop).

Como as listas usam espaços como delimitadores - isto é, um espaço significa uma mudança para o próximo item da lista - os arquivos que possuem espaços no nome não são muito amigáveis. Por enquanto, vamos trabalhar 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 básico sobre scripts do bash.

Nele, digite o seguinte código:

for i in item1 item2 item3 item4 item5 item6; do echo “$i” done

Quando você executa o script, você deve apenas obter esses itens da lista como saída.
Quando você executa o script, você deve apenas obter esses itens da lista como saída.
Muito simples, certo? Vamos ver o que acontece se mudarmos um pouco as coisas. Mude seu script para que ele diga isto:
Muito simples, certo? Vamos ver o que acontece se mudarmos um pouco as coisas. Mude seu script para que ele diga isto:

for i in *; do echo “$i” done

Quando você executa este script em uma pasta, você deve obter uma lista de arquivos que ele contém como saída.
Quando você executa este script em uma pasta, você deve obter uma lista de arquivos que ele contém como saída.
Agora, vamos mudar 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!
Agora, vamos mudar 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!

for i in $@; do zip archive “$i” done

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 executo o script com vários arquivos de entrada.
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 executo o script com vários arquivos de entrada.
Você pode ver quais arquivos estão na minha pasta. Eu executei o comando com seis argumentos e cada arquivo foi adicionado a um arquivo compactado chamado "archive.zip". Fácil, certo?
Você pode ver quais arquivos estão na minha pasta. Eu executei 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 em listas de arquivos. Por exemplo, você pode copiar todos os argumentos do script em um arquivo compactado, mover os originais para uma pasta diferente e proteger automaticamente a cópia do arquivo zip para um computador remoto. Se você configurar arquivos-chave com SSH, nem precisará inserir sua senha, e poderá até mesmo dizer ao script para excluir o arquivo zip após o upload.

O uso de loop for 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 isso é 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 no script!

Recomendado: