Como executar muitos arquivos no mesmo diretório de forma minimalista, SECA e bonita?

3

Eu uso o Ubuntu 16.04 e tenho um arquivo de localização, um arquivo que executa muitos arquivos, que eu peguei depois de baixar meu próprio projeto do GitHub para minha máquina.

Este arquivo contém um script Bash e é denominado localize.sh . Eu corro em uma subsessão via ~/${repo}/localize.sh .

O arquivo contém muitas linhas, todas com o mesmo padrão básico (veja abaixo), para executar todos os arquivos relevantes na sub-sessão.

Este é o conteúdo real desse arquivo:

#!/bin/bash
~/${repo}/apt/security.sh
~/${repo}/apt/lemp.sh
~/${repo}/apt/certbot.sh
~/${repo}/apt/misc.sh

~/${repo}/third-party/pma.sh
~/${repo}/third-party/wp-cli.sh

~/${repo}/conf/nginx.sh
~/${repo}/conf/php.sh
~/${repo}/conf/crontab.sh

~/${repo}/local/tdm.sh

Pode-se notar o padrão repetitivo ~/${repo}/ .

Não é um grande problema, mas ainda seria bom reduzir esses caracteres redundantes, pois esse arquivo deve ficar maior.

Qual é a maneira mais mínima possível de obter uma versão DRY ( Don't Repeat Yourself esse código?

Uma única linha longa não é algo que eu gostaria de usar, neste caso.

Edit: Por princípio, não há e não deve haver nenhum outro arquivo nos diretórios listados, além dos arquivos listados em localize.sh .

Além disso, pode ser que o nome localize.sh , assim como chamar a ação do arquivo localization , seja uma má abordagem; Por favor, me critique se você acha que é ruim, em uma nota lateral.

    
por user9303970 12.02.2018 / 14:37

5 respostas

0

Com base na resposta de Marc, presumo que a solução mais curta seria algo assim:

$ myPath="$HOME/$repo"; find ${path} -type f -iname "*.sh" -exec {} \;
file_1
file_2
...
    
por 13.02.2018 / 13:58
8

Não está claro se você está executando todos os scripts nos diretórios relevantes, mas se estiver, você pode encontrar run-parts useful:

for subdir in apt third-party conf local
do
    run-parts --regex '\.sh$' ~/${repo}/${subdir}
done

Observe que isso executará os scripts em ordem alfanumérica em cada diretório, portanto, se o pedido for significativo dentro de um subdiretório, será necessário renomeá-los (ou numerá-los). Você pode ver o que o run-parts fará antecipadamente, executando-o com a opção --test :

apt/certbot.sh
apt/lemp.sh
apt/misc.sh
apt/security.sh
third-party/pma.sh
third-party/wp-cli.sh
conf/crontab.sh
conf/nginx.sh
conf/php.sh
local/tdm.sh
    
por 12.02.2018 / 14:48
2

O que é um simples e curto 'encontrar $ {repo} -exec {} \?'?

Meus scripts de exemplo apenas echo "foo" ou "bar" ou "baz":

$ repo=~/scripts/bash/foo; find ${repo} -type f -iname "*.sh" -exec {} \;
foo
baz
bar

você pode até usar alias para encurtá-lo:

$ alias run_myscripts='repo=~/scripts/bash/foo; find ${repo} -type f -iname "*.sh" -exec {} \;'

ou     $ alias run_myscripts = 'localizar ~ / scripts / bash / foo -tipo f -iname "* .sh" -exec {} \;'

Em seguida, basta executar

run_myscripts

Apenas percebe que os arquivos precisam do sinalizador de execução. Se eles não têm ou você não tem certeza, você só precisa estender o comando 'find ... -exec' como este:

find ${repo} -type f -iname "*.sh" -exec bash {} \;'

Editar: Ok, não percebi que a ordem deveria ser mantida. Isso vai mudar um pouco e eu acho que uma boa maneira é colocar o pedido em um arquivo de texto e envolver uma "linha de leitura ao ler" em torno de uma linha de execução.

while read line; do 
    bash ~/${repo}/$line
done < ordered_scripts.txt 

em ordered_scripts.txt você pode definir a ordem correta.

apt/security.sh
apt/lemp.sh
apt/certbot.sh
apt/misc.sh
third-party/pma.sh
third-party/wp-cli.sh
conf/nginx.sh
conf/php.sh
conf/crontab.sh
local/tdm.sh
    
por 13.02.2018 / 12:58
1

Supondo que todos os scripts estejam localizados no diretório pai comum ~/${repo} , você pode colocá-los em uma matriz e fazer um loop sobre ele:

SCRIPTS=(apt/security.sh apt/lemp.sh apt/certbot.sh apt/misc.sh
         tp/pma.sh tp/wp-cli.sh conf/nginx.sh conf/php.sh conf/crontab.sh
         local/tdm.sh)

for SCRIPT in ${SCRIPTS[@]}; do
    ~/${repo}/${SCRIPT}
done
    
por 12.02.2018 / 14:44
0

Com o GNU Parallel:

parallel ::: ~/${repo}/*/*.sh

Se precisar ser serial:

parallel -j1 ::: ~/${repo}/*/*.sh

Isso executará os scripts em ordem alfanumérica, portanto, se a ordem for significativa, renomeie os diretórios e pastas da seguinte forma: 01_apt/01_security.sh Use --dry-run para ver o que seria executado.

Se isso corresponder a muitos arquivos (por exemplo, outros diretórios), mencione os diretórios diretamente.

parallel ::: ~/${repo}/{apt,third-party,conf,local}/*.sh

Se o pedido é importante:

parallel -j1 ::: \
  ~/${repo}/{apt/{security,lemp,certbot,misc},third-party/{pma,wp-cli},conf/{nginx,php,crontab},local/tdm}.sh

O último vai um pouco contra o seu desejo de evitar uma longa fila.

Uma versão vertical que permite linhas vazias:

parallel -rj1 ~/${repo}/{} <<_EOF
apt/security.sh
apt/lemp.sh
apt/certbot.sh
apt/misc.sh

third-party/pma.sh
third-party/wp-cli.sh

conf/nginx.sh
conf/php.sh
conf/crontab.sh

local/tdm.sh
_EOF
    
por 15.02.2018 / 18:20