최소한의, DRY, 아름다운 방식으로 동일한 디렉토리에 있는 여러 파일을 실행하는 방법은 무엇입니까?

최소한의, DRY, 아름다운 방식으로 동일한 디렉토리에 있는 여러 파일을 실행하는 방법은 무엇입니까?

저는 Ubuntu 16.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를 구현하는 가장 간단한 방법은 무엇입니까(반복하지 마세요이 코드의 버전은 무엇입니까?

저는 개인적으로 이 경우 긴 와이어를 사용하고 싶지 않습니다.

편집: 원칙적으로 .txt에 나열된 파일 이외의 다른 파일은 나열된 디렉터리에 존재하지 않으며 존재해서는 안 됩니다 localize.sh.


localize.sh또한 이름이나 파일을 호출하는 동작은 localization좋지 않은 접근 방식일 수 있습니다. 잘못 작성되었다고 생각되면 저를 비판하고 참고 사항에 지적해 주시기 바랍니다.

답변1

실행 중인지 확실하지 않음모두스크립트는 관련 디렉터리에 있지만, 그렇다면 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

답변2

간단하고 짧은 "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 

order_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

답변3

모든 스크립트가 공통 상위 디렉토리에 있다고 가정하면 ~/${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

답변4

GNU 병렬 처리 사용:

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

직렬화가 필요한 경우:

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

그러면 스크립트가 영숫자 순서로 실행되므로 순서가 중요한 경우 디렉터리와 폴더의 이름을 다음과 같이 바꾸면 실행될 내용을 확인할 01_apt/01_security.sh수 있습니다.--dry-run

일치하는 파일이 너무 많으면(예: 다른 디렉터리) 해당 디렉터리를 직접 언급하세요.

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

관련 정보