web-dev-qa-db-ja.com

同じディレクトリ内の多くのファイルを最小限のDRYできれいな方法で実行するにはどうすればよいですか?

私はUbuntu16.04を使用しており、自分のGitHubプロジェクトを自分のマシンにダウンロードした後に取得したローカリゼーションファイル(多くのファイルを実行するファイル)があります。

このファイルにはBashスクリプトが含まれており、名前はlocalize.shです。 ~/${repo}/localize.shを介してサブセッションで実行します。

このファイルには、サブセッションで関連するすべてのファイルを実行するために、すべて同じ基本パターン(以下を参照)の行が多数含まれています。

これは、そのファイルの実際の内容です。

#!/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

~/${repo}/パターンが繰り返されていることに気付くでしょう。

これは大きな問題ではありませんが、このファイルが大きくなるため、これらの冗長な文字を減らすことをお勧めします。

そのコードのDRY( Do n’t Repeat Yourself バージョンを達成するために可能な最小限の方法は何ですか?

この場合、1つの長い行は私が個人的に使用したいものではありません。

編集:原則として、localize.shにリストされているファイル以外に、リストされているディレクトリには他のファイルはありません。


また、localize.shという名前、およびファイルlocalizationのアクションを呼び出すことは悪いアプローチである可能性があります。悪いと思うなら、サイドノートで私を批判してください。

3
user9303970

マークの回答に基づいて、最短の解決策は次のようになると思います。

$ myPath="$HOME/$repo"; find ${path} -type f -iname "*.sh" -exec {} \;
file_1
file_2
...
0
user9303970

実行しているかどうかは不明ですall関連するディレクトリ内のスクリプトですが、実行している場合は、run-partsが役立つ場合があります。

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

これにより、各ディレクトリ内でスクリプトが英数字順に実行されるため、サブディレクトリ内で順序が重要な場合は、名前を変更する(または番号を付ける)必要があります。 run-partsオプションを指定して実行すると、--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
8
Stephen Kitt

単純で短い 'find $ {repo} -exec {} \;'はどうですか?

私のサンプルスクリプトは、「foo」または「bar」または「baz」をエコーするだけです。

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

エイリアスして短縮することもできます。

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

または$ alias run_myscripts = 'find〜/scripts/bash/foo -type f -iname "* .sh" -exec {} \;'

次に実行するだけ

run_myscripts

ファイルに実行フラグが必要であることに注意してください。彼らがそれを持っていないか、あなたが確信が持てない場合は、次のように 'find ...- exec'コマンドを拡張する必要があります。

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

編集:わかりました、順序を維持する必要があることに気づいていませんでした。これにより少し変更されます。テキストファイルで注文し、実行行を「読み取り中の行」で囲むのが良い方法だと思います。

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

ordered_scripts.txtで、正しい順序を定義できます。

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
2
Marc

すべてのスクリプトが共通の親ディレクトリ内にあると仮定します~/${repo}それらを配列に入れて、ループすることができます。

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
1
Richard Neumann

GNU Parallel:

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

シリアルにする必要がある場合:

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

これにより、スクリプトが英数字順に実行されるため、順序が重要な場合は、dirsとフォルダーの名前を次のように変更します。01_apt/01_security.sh 使用する --dry-run何が実行されるかを確認します。

これがあまりにも多くのファイル(他のdirなど)に一致する場合は、dirに直接言及してください。

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

順序が重要な場合:

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

最後は、長蛇の列を避けたいというあなたの願いに少し反します。

空の行を許可する垂直バージョン:

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
0
Ole Tange