일상적인 작업을 단순화하기 위해 스크립트를 만들고 있습니다. 매일 회사 서버 내에서 무언가를 검색해야 합니다. 괜찮습니다. 하지만 이제는 각 개체를 하위 디렉터리로 분리했습니다. 저는 기존 쉘 스크립트가 특정 디렉토리 내의 모든 하위 디렉토리에서 반복적으로 실행되는 솔루션을 찾고 있습니다. 어떻게 해야 하나요? 저는 Linux를 처음 접했고 아직 배우고 있습니다.
이것은 내 스크립트입니다.
#!/bin/bash
MainDir=/path/to/dir/containing/subdirs
# cd into dir
cd $MainDir
for dir in $(ls); do
#fetch start time of uut
grep -i "01_node_setup" $dir/his_file | tail -1 >> /home/xtee/sst-logs.out
#check if sysconfig.out exists
if [ -f $dir/sysconfig.out];
then
grep -A 1 "Drive Model" $dir/sysconfig.out | tail -1 >> /home/xtee/sst-logs.out
else
grep -m 1 "Pair0 DIMM0" $dir/node0/trans_file_prev/*setupsys* | tail -1 >> /home/xtee/sst-logs.out
fi
done
#cd back to where we started
cd $OLDPWD
좋은 사람이 제가 대본을 작성하는 데 도움을 주었고 그렇게 해서 위의 대본이 나왔습니다. 그러나 binary file /some/subdirectory/
grep 출력 대신 sst-logs.out 파일을 표시하여 잘 작동합니다 . 스크립트에 어떤 문제가 있나요?
답변1
찾기를 통해 다음을 구할 수 있습니다.
find /your/dir/with/subdirs -type d -exec sh -c 'cd "{}" ; /path/to/your/script.sh ;' \;
답변2
스크립트에 몇 가지 문제가 있습니다.
cd $MainDir
이렇게 하는 것이 좋습니다 cd "$MainDir"
. 중요하지는 않지만 발전하는 데 좋은 습관입니다. 변수가 따옴표 없이 확장되면 변수의 값이 단어로 분할되고 각 단어는 쉘 와일드카드 패턴으로 처리됩니다. 따라서 $MainDir
공백이 포함되어 있거나\[?*
파일 이름이 일치하는 경우 큰따옴표를 추가해도 문제가 없습니다. 이러한 추가 확장을 피할 수 있습니다. 명령 대체( )의 경우에도 마찬가지입니다 $(somecommand)
.변수 및 명령 대체에는 항상 큰따옴표를 사용하십시오.분할과 파일 이름이 일치하길 원하는지 모르는 경우.
for dir in $(ls); do
출력을 구문 분석하지 않습니다.ls
. ls
스크립트에서 이를 사용할 필요가 거의 없습니다 . 위에서 언급한 대로 명령 대체 결과는 와일드카드 패턴으로 처리되는 단어로 분할되므로 인쇄할 수 없는 문자가 깨질 가능성이 있을 $(ls)
뿐만 ls
아니라 공백과 와일드카드도 깨집니다. 셸에는 디렉터리에 파일 이름을 나열하는 기능이 내장되어 있습니다.
for dir in *; do
이렇게 하면 for dir in */; do
현재 디렉터리의 하위 디렉터리만 일치하고 다른 유형의 파일은 일치하지 않습니다.
if [ -f $dir/sysconfig.out];
옆에 있는 문자가 쉘 구두점인 경우를 제외하고 대괄호 양쪽에 공백이 필요합니다: ();&|<>
. 다시 한 번, 변수 대체 주위에 큰따옴표를 넣으십시오(이는 변수 대체가 있는 다른 모든 위치에 적용됩니다).if [ -f "$dir/sysconfig.out" ];
#cd back to where we started cd $OLDPWD
이것은 쓸모가 없습니다. 프로세스가 종료되려고 하며 현재 디렉터리를 변경해도 아무 영향이 없습니다. 각 프로세스에는 고유한 현재 디렉토리가 있습니다. 스크립트 내에서 이를 변경해도 스크립트를 호출하는 프로그램에는 영향을 미치지 않습니다.
질문하신 이유로 돌아가서 원하는 것이 무엇인지 명확하지 않습니다. " binary file /some/subdirectory/
"는 별로 의미가 없습니다. 디렉토리와 함께 이 메시지를 받지 못할 것입니다. 더 나은 도움을 받으려면 오류 메시지를 복사하여 붙여넣으세요. 당신은해야항상 복사 붙여넣기 오류 메시지온라인으로 도움을 요청할 때.
귀하의 설명에 따르면 파일이 한 디렉터리 더 깊은 것 같습니다. 이 경우 행을 다음 for dir in */; do
으로 변경하십시오.
for dir in */*/; do
답변3
이를 수행하는 방법에는 여러 가지가 있습니다. for 루프에서 기존 스크립트를 실행하거나 find 및 xargs를 사용하거나 grep의 -r
일명 --recursive
옵션을 사용할 수도 있습니다.
가장 간단한 방법은 아마도 기존 스크립트 주위에 for 루프 래퍼를 작성하는 것입니다. 예를 들어:
#! /bin/bash
cd /path/to/top/level/directory
for d in */ ; do
pushd $d
# call your script here
popd
done
답변4
find
@rush의 제안이 약간 개선되어 스위치를 사용하는 대신 다음을 수행하면 명령 추가를 피할 수 있습니다 .-exec
cd
find /path/to/dir/containing/subdirs -type d -execdir /path/to/your/script.sh \;
이렇게 하면 for
원본 스크립트의 루프를 완전히 피할 수 있습니다.