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
...
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.
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
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
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
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