Aplicações variadas
Descompactar um arquivo para um diretório específico
tar -zxvf arquivo.tar.gz -C <nome_diretório>
Loop com tempo
1 Loop a cada 30 minutos.
#!/bin/bash
data_inicial="202001011400" # Formato YYYYMMDDhhmm
data_final="202001011600"
while [ ${data_inicial} -le ${data_final} ]; do
echo ${data_inicial}
curr=`date -d "${data_inicial:0:8} ${data_inicial:8:2}:${data_inicial:10:2} 30 minutes " +"%Y%m%d %H:%M"`
# Suas instruções...
data_inicial=`date -d "${curr}" +%Y%m%d%H%M`
# Recorte nas variáveis para serem utilizadas para outros fins. Esse trecho é opcional.
ano=${data_inicial:0:4}
mes=${data_inicial:4:2}
dia=${data_inicial:6:2}
hora=${data_inicial:8:2}
min=${data_inicial:10:2}
done
O resultado será:
202001011400
202001011430
202001011500
202001011530
202001011600
2 Outro exemplo com loop, dessa vez, a cada 12 horas.
data_inicial="2020010100" # AAAAMMDDhh
data_final="2020010300"
while [ ${data_inicial} -le ${data_final} ]; do
echo ${data_inicial}
# Suas instruções...
data_inicial=`date -d "${data_inicial:0:8} ${data_inicial:8:2}:00 12 hours " +"%Y%m%d%H"`
done
O resultado será:
2020010100
2020010112
2020010200
2020010212
2020010300
3 Loop variando dia a dia.
#!/bin/bash
data_inicial="20200101" # Formato AAAAMMDD
data_final="20200110"
while [ ${data_inicial} -le ${data_final} ]
do
echo ${data_inicial}
# Suas intruções...
data_inicial=`date -u +"%Y%m%d" -d "${data_inicial} 1 day "`
done
O resultado será:
20200101
20200102
20200103
20200104
20200105
20200106
20200107
20200108
20200109
20200110
4 Outra opção com loop variando dia a dia.
#!/bin/bash
data_inicial="2020010100" # Formato AAAAMMDD00
data_final="2020011000"
while [ ${data_inicial} -le ${data_final} ]
do
echo ${data_inicial}
# Suas intruções...
data_inicial=$(date -u -d "${data_inicial:0:8} ${data_inicial:8:10}:00 24 hours" +"%Y%m%d%H")
done
O resultado será:
2020010100
2020010200
2020010300
2020010400
2020010500
2020010600
2020010700
2020010800
2020010900
2020011000
5 Loop ao longo das previsões do modelo GFS.
#!/bin/bash
# Ajuste os parâmetros abaixo de acordo com as suas necessidades.
PREV=0 # Horário que começa a previsão de interesse (f000).
PRAZO=384 # Quantidade de previsões em horas desejadas. São 384 horas.
dPREV=3 # Intervalo temporal em horas entre cada previsão desejada.
while [[ ${PREV} -le ${PRAZO} ]]
do
fcst=`echo ${PREV} | awk '{printf("%.3d",$1)}'`
# Adicione suas instruções.
echo "Arquivo: gfs.t00z.pgrb2.0p25.${fcst}"
let PREV=${PREV}+${dPREV}
done
# A saída será da seguinte forma:
# Arquivo: gfs.t00z.pgrb2.0p25.000
# Arquivo: gfs.t00z.pgrb2.0p25.003
# Arquivo: gfs.t00z.pgrb2.0p25.006
# Arquivo: gfs.t00z.pgrb2.0p25.009
# Arquivo: gfs.t00z.pgrb2.0p25.012
# Arquivo: gfs.t00z.pgrb2.0p25.015
# Arquivo: gfs.t00z.pgrb2.0p25.018
# Arquivo: gfs.t00z.pgrb2.0p25.021
.
.
.
# Arquivo: gfs.t00z.pgrb2.0p25.381
# Arquivo: gfs.t00z.pgrb2.0p25.384
Remover caracteres estranhos no Linux
Em algumas situações quando se copiam programas feitos no Windows para o Linux, alguns caracteres indesejáveis surgem, gerando o erro abaixo.
Supondo que o script escrito em Shell tenha sido feito no Windows com o nome de
teste.sh
. Ao tentar executá-lo no Linux, a mensagem de erro surgirá:
./teste.sh: line 2: $'\r': command not found
Esse
\r
é o problema. E isso pode ser resolvido por meio da instalação dodos2unix
com o comando abaixo:
sudo apt install dos2unix
Após a instalação, basta digitar:
dos2unix teste.sh
Para remover os caracteres estranhos. Dessa forma, é possível utilizar o seu script sem problemas.
Saber o número de núcleos do seu processador
Basta digitar no terminal do Linux o comando abaixo:
nproc
Saber qual é a versão do sistema operacioanl Linux
lsb_release -rd
Resultado:
Description: Ubuntu 18.04.3 LTS
Release: 18.04
Utilizar o wget com usuário e senha
wget -c -r http://www.siteexemplo.com.br/arquivos.zip --http-user=nome_usuario --http-passwd=senha_usuario
Utilizar o wget para alterar o nome do arquivo.
Nesse exemplo, será feito o download do arquivo
precip.mon.mean.nc
, e deseja-se que o mesmo tenha outro nome, isto é,prec.nc
. O comando abaixo realizará essa tarefa.
wget ftp://ftp.cdc.noaa.gov/Datasets/cmap/enh/precip.mon.mean.nc -O prec.nc
Utilizar o rename para renomar arquivos em lote
Comando bastante útil para renomear vários arquivos de uma vez ou em lote.
Para instalar:
sudo apt-get install rename
Exemplo de uso. Supondo que se deseja realizar algumas conversões com o
gdal
. Os arquivos de entrada possuem o seguinte nomeYYYYMMDD.tif
(são vários arquivos com datas distintas) e ofor
abaixo alterará o nome desses arquivos paraYYYYMMDD.tif.hard-typed
. A última linha mostrará o uso do comandorename
. Nota-se que a lógica é semelhante a utilizada nosed
, isto é,s
para substituir de uma só vez o.hard-typed
pornada
ouvazio
(//
) em todos os arquivos.
#!/bin/bash
for original in $(ls -1 *.tif)
do
gdal_translate -of GTiff -ot Float32 -b 1 -co "TILED=YES" ${original} ${original}.hard-typed
done
# Remove arquivos desnecessários.
rm -rf *.tif
# Uso do rename para renomear vários arquivos de uma vez só. O que foi feito? será substituido no nome do arquivo o ".hard-typed" por "espaço vazio" ou //.
rename 's/.hard-typed//' *.hard-typed
Forma alternativa de renomear arquivos em lote usando o loop for e basename
Imagine a seguinte lista de arquivos (6 no total) no formato NetCDF:
IGBP_c6_MAPBIOMA_v3_2001_001_RF_cnew.nc
IGBP_c6_MAPBIOMA_v3_2002_001_RF_cnew.nc
IGBP_c6_MAPBIOMA_v3_2003_001_RF_cnew.nc
IGBP_c6_MAPBIOMA_v3_2004_001_RF_cnew.nc
IGBP_c6_MAPBIOMA_v3_2005_001_RF_cnew.nc
IGBP_c6_MAPBIOMA_v3_2006_001_RF_cnew.nc
O objetivo consiste em converter do formato NetCDF para o formato tif utilizando o gdal
. Lembrando que isso é apenas um exemplo de como utilizar a lógica do loop for
e o uso do basename
para obter apenas o nome do arquivo sem sua extensão.
Esse procedimento é feito com o script abaixo:
#!/bin/bash
for nome_arquivo in *.nc
do
gdal_translate -of GTiff -a_srs EPSG:4326 $nome_arquivo $(basename $nome_arquivo .nc).tif
done
O trecho do código $(basename $nome_arquivo .nc)
imprime apenas o nome do arquivo sem sua extensão, lembrando que esse é o nome do arquivo de saída, resultando em:
IGBP_c6_MAPBIOMA_v3_2008_001_RF_cnew
O trecho abaixo:
$(basename $nome_arquivo .nc).tif
é o mesmo que:
IGBP_c6_MAPBIOMA_v3_2006_001_RF_cnew.tif
Utilizar o parallel no Linux
O
parallel
é excelente quando se deseja realizar várias tarefas de uma só vez.Para instalar o
parallel
basta digitar:
sudo apt-get install parallel
1 Exemplo de como converter arquivos em lote. No exemplo abaixo, há 90 arquivos (01/01/2019 a 31/03/2019) no formato NetCDF com o seguinte nome RF.ANL.LAT.TOPO.AAAAMMDD00.nc
(AAAA = ano, MM = mês e DD = dia). O objetivo consiste em converter do formato NetCDF para o formato tif utilizando o gdal. Em vez de fazer um loop para converter cada arquivo individualmente, usamos o parallel
para converter vários arquivos de uma só vez.
Mas antes, é imporantante saber o número de processadores do seu computador. Para saber isso, basta digitar no terminal Linux, o comando abaixo:
nproc
O valor do resultado acima será utilizado na variável
num_processadores
do script abaixo. Por exemplo, o resultado foi 100, claro que não serão utilizados os 100 processadores, mas serão utilizados 30 (escolha aleatória) na variávelnum_processadores
.Observação: Nunca utilize todos os processadores do seu computador porque há grande chances de travá-lo, e com isso, a necessidade de reiniciar o sistema.
O arquivo
datas.txt
(será criado no script abaixo) conterá a lista com os 90 arquivos (ou dias) de comandos abaixo (mostrando apenas algumas linhas, no total são 90 linhas de comando) que foi gerada dentro do loop do while (do script abaixo).Apenas lembrando que as linhas abaixo convertem o arquivo NetCDF para tif utilizando o gdal para cada dia:
gdal_translate -of GTiff -a_srs EPSG:4326 RF.ANL.LAT.TOPO.2019010100.nc RF.ANL.LAT.TOPO.2019010100.tif
gdal_translate -of GTiff -a_srs EPSG:4326 RF.ANL.LAT.TOPO.2019010200.nc RF.ANL.LAT.TOPO.2019010200.tif
gdal_translate -of GTiff -a_srs EPSG:4326 RF.ANL.LAT.TOPO.2019010300.nc RF.ANL.LAT.TOPO.2019010300.tif
gdal_translate -of GTiff -a_srs EPSG:4326 RF.ANL.LAT.TOPO.2019010400.nc RF.ANL.LAT.TOPO.2019010400.tif
gdal_translate -of GTiff -a_srs EPSG:4326 RF.ANL.LAT.TOPO.2019010500.nc RF.ANL.LAT.TOPO.2019010500.tif
.
.
.
gdal_translate -of GTiff -a_srs EPSG:4326 RF.ANL.LAT.TOPO.2019032700.nc RF.ANL.LAT.TOPO.2019032700.tif
gdal_translate -of GTiff -a_srs EPSG:4326 RF.ANL.LAT.TOPO.2019032800.nc RF.ANL.LAT.TOPO.2019032800.tif
gdal_translate -of GTiff -a_srs EPSG:4326 RF.ANL.LAT.TOPO.2019032900.nc RF.ANL.LAT.TOPO.2019032900.tif
gdal_translate -of GTiff -a_srs EPSG:4326 RF.ANL.LAT.TOPO.2019033000.nc RF.ANL.LAT.TOPO.2019033000.tif
gdal_translate -of GTiff -a_srs EPSG:4326 RF.ANL.LAT.TOPO.2019033100.nc RF.ANL.LAT.TOPO.2019033100.tif
Como foi mencioando, em vez de fazer isso dia a dia por meio de um loop, podemos realizar essa tarefa, por exemplo, executando 30 linhas de comando por vez (
num_processadores
= “30”).O comando
split
divide o arquivodatas.txt
(que contém todas as 90 linhas gerada no loop while) de forma igual, isto é, de 30 em 30 (essa foi a escolha com base no total de processadores do computador), gerando assim os seguintes arquivos abaixo. Após a aplicação dosplit
nodatas.txt
que contém 90 linhas de comando, foram gerados os 3 arquivos abaixo:
datas_aa
datas_ab
datas_ac
Cada um desses arquivos (
datas_aa
,datas_ab
edatas_ac
) possui 30 linhas de comandos mudando apenas a data.Exemplo de uma linha de comando:
gdal_translate -of GTiff -a_srs EPSG:4326 RF.ANL.LAT.TOPO.2019032700.nc RF.ANL.LAT.TOPO.2019032700.tif
O loop da geração do comando
parallel
será feito com o comando abaixo por meio do scriptcomandos.sh
(gerado pelo script abaixo):
parallel -j 30 -- < datas_aa
parallel -j 30 -- < datas_ab
parallel -j 30 -- < datas_ac
O script abaixo se chama
executa.sh
(pode ser qualquer nome) que fará todo o serviço:
#!/bin/bash
data_inicial="20190101"
data_final="20191231"
rm -f datas.txt # Remove o arquivo datas.txt para evitar erro.
# Gera o intervalo de interesse a ser executado.
while [ ${data_inicial} -le ${data_final} ]; do
echo ${data_inicial}
# Geração do arquivo datas.txt
echo "gdal_translate -of GTiff -a_srs EPSG:4326 RF.ANL.LAT.TOPO.${data_inicial}00.nc RF.ANL.LAT.TOPO.${data_inicial}00.tif" >> datas.txt
data_inicial=`date -u +"%Y%m%d" -d "${data_inicial} 1 day "`
done
# Define o número de processadores a serem utilizados com base no comando acima (nproc).
num_processadores="30"
# Vai gerar novos arquivos a partir de datas.txt que serão separados em 30 (num_processadores) partes iguais.
split -l ${num_processadores} datas.txt datas_
rm -f comandos.sh # Limpa para evitar erro.
# Cria um arquivo chamado comandos.sh que contém todas as linhas de comandos para executar o parallel.
for arq in $(ls -1 datas_*); do
echo "parallel -j ${num_processadores} -- < $arq" >> comandos.sh
done
chmod +x comandos.sh # Torna o arquivo executável.
nohup ./comandos.sh & # Para executar o script.
exit
Depois, basta monitorar o arquivo nohup
com o comando:
tail -f nohup
A vantagem de utilizar o
parallel
está no fato de realizar uma tarefa simples executando várias linhas de comando de uma só vez.
2 Esse exemplo consiste em baixar os dados de precipitação diária utilizando o parallel
. Como afirmado anteriormente, em vez de baixar um arquivo por vez, é possível baixar vários de uma só vez.
O script fictício chamado de
get_prec.sh
baixa um arquivo por vez e tem como parâmetro de entrada a data no formatoAAAAMMDD
, com isso é possível realizar o downlod de vários arquivos, claro, respeitando o número de processadores do seu cumputador.Exemplo de como executar:
./get_prec.sh 20200130
Porém, com o uso o
parallel
podemos baixar mais arquivos em lote de acordo conforme o script abaixo:
#!/bin/bash
data_inicial="20000602"
data_final="20200519"
rm -f datas.txt # Limpa para evitar erro.
# Gera o intervalor de interesse a ser executado.
nome_script="get_prec.sh" # Altere aqui o nome do script.
# Loop no tempo para criar o arquivo datas.txt
while [ ${data_inicial} -le ${data_final} ]; do
echo ${data_inicial}
echo "./${nome_script} ${data_inicial}" >> datas.txt
data_inicial=`date -u +"%Y%m%d" -d "${data_inicial} 1 day "`
done
num_processadores="40" # Número de processadores a serem utilizados.
# Vai gerar novos arquivos a partir de datas.txt que serão separados em 40 (num_processadores) partes iguais.
split -l ${num_processadores} datas.txt datas_
rm -f comandos.sh # Limpa para evitar erro.
# Cria um arquivo chamado comandos.sh que contém todas as linhas de comandos para executar em paralelo.
for arq in $(ls -1 datas_*); do
echo "parallel -j ${num_processadores} -- < $arq" >> comandos.sh
done
chmod +x comandos.sh # Torna o arquivo executável.
nohup ./comandos.sh &
Depois, basta monitorar o arquivo nohup
com o comando:
tail -f nohup &
3 Outra forma de utilizar o parallel. Neste exemplo, será feito o uso do operador mergetime para juntar vários dias de um determinado ano.
#!/bin/bash
for ano in $(seq 2010 2018)
do
echo "cdo -s -O mergetime RF.${ano}????00.nc tmp01.RF.${ano}.nc" >> lista.txt
done
nohup parallel -j 12 < lista1.txt > lista1.log
O valor 12
veio a partir do comando nproc
que digita-se no terminal. O valor obtido divide-se por 2.
Por exemplo, ao digitar o nproc
foi retornado o valor 24
, e 24/2 = 12.
Este número representa o número de núcleos do seu computador.
Se você usar todos os núcleos, é bem provável que a sua máquina possa travar.
O arquivo lista.txt
terá o seguinte conteúdo.
cdo -s mergtime RF.2010????00.nc tmp01.RF.2010.nc
cdo -s mergtime RF.2011????00.nc tmp01.RF.2011.nc
cdo -s mergtime RF.2012????00.nc tmp01.RF.2012.nc
cdo -s mergtime RF.2013????00.nc tmp01.RF.2013.nc
cdo -s mergtime RF.2014????00.nc tmp01.RF.2014.nc
cdo -s mergtime RF.2015????00.nc tmp01.RF.2015.nc
cdo -s mergtime RF.2016????00.nc tmp01.RF.2016.nc
cdo -s mergtime RF.2017????00.nc tmp01.RF.2017.nc
cdo -s mergtime RF.2018????00.nc tmp01.RF.2018.nc
Qual a vantagem de se fazer isso? Em vez de gerar um loop para cada ano, os 9 comandos serão executados de uma vez só, economizando tempo de máquina.
Localizar onde está sendo executado um comando
O pwdx
é nativo do Linux e é excelente para identificar qual o diretório que um determinado processo foi executado.
Sintaxe:
sudo pwdx PID
O
PID
(Process Identifier) é um número de identificação que o sistema fornece quando se executa um processo. Por exemplo, ao executar um programa, o mesmo gerará um PID.Como saber o PID de um processo? Basta utilizar o
htop
, e verificar a primeira coluna desse comando.Para instalar o
htop
basta digitar:sudo apt install htop
Exemplo de uso:
sudo pwdx 3859
Será retornado o diretório do processo PID: 3859.
Exemplo de retorno:
/mnt/produtos/meteorologia