일련의 "histogram_0000_0000" 폴더가 포함된 상위 폴더가 있습니다. 모든 폴더에서 "out.txt" 파일을 검색하고 폴더에서 파일이 발견될 때마다 이를 반환하는 bash 스크립트를 만들려고 합니다(파일이 모든 폴더에 있는지 확인하기 위해). 내가 얻은 스크립트는 다음과 같습니다.
#!/bin/bash
joblist='job_list.txt'
njobs=`wc ${joblist} | awk '{print $1}'`
cwd=`pwd`
for ((i=1 ; i <= ${njobs} ; i++ )); do
folder=`awk '(NR=='${i}'){print}' ${joblist}`
echo $folder
cd ${folder}
if [ find -name "out.txt" ]
then
echo out.txt found in $folder
fi
cd ${cwd}
done
하지만 실행할 때마다 오류가 발생합니다.
./checkrun.sh: 10행: [: -name: 이진 연산자 필요
주위를 둘러보고 "[[" 및 "]]"를 사용해 보았지만 여전히 왜 운이 좋은지 모르겠습니다! 어떤 도움이라도 좋을 것입니다. 고마워요, -잭
답변1
[
... ]
문자열 또는 숫자 표현식을 테스트합니다. 명령이 일치하는지 확인하려면 find
출력(비어 있지 않은 문자열, 를 사용하여 테스트 -n
)을 제공하는지 테스트해야 합니다.
if [[ -n "$(find -name 'out.txt')" ]]
then
echo "out.txt found in $folder"
fi
$(...)
명령의 출력을 캡처하기 위해 더 이상 사용되지 않는 역따옴표 대신 최신 구문을 사용하고 있습니다 `...`
.
다른 제안,
행 수를 얻기
njobs=
위해 wc ${joblist} | awk '{print $1}'``를 단순화할 수 있습니다 .njobs=$(wc -l <"$joblist")
$i
awk
변수 로 전달되었으며,folder=$(awk -v i="$i" 'NR==i {print}' "$joblist}")
cd
하위 폴더로 이동한 다음 를 사용하여cd
원래 위치로 돌아가지 마십시오 . 하위 디렉터리를 참조하려면 상대 경로를 사용하고,cd
제한된 컨텍스트에서 하위 디렉터리를 유지하려면 하위 쉘을 사용하세요. 여기서는 첫 번째 방법을 사용합니다.echo "$folder" if [[ -n "$(find "$folder" -name 'out.txt')" ]] then echo "out.txt found in $folder" fi
항상 상대 경로인 경우
$folder
경로로 사용되는 곳마다 "./$folder"로 참조됩니다. 이렇게 하면-
대시( )로 시작하여 대시( )를 일련의 옵션으로 해석하려는 명령에 혼동을 줄 수 있습니다.쉘에는
bash
이미 현재 작업 디렉토리에 대한 변수가 있으므로 다음cwd=`pwd`
과 같이 단순화할 수 있습니다.cwd="$PWD"
사용https://shellcheck.net/코드를 확인하세요. (프라이빗 코드 공유가 걱정된다면 로컬에 설치해도 됩니다.)
답변2
#!/bin/bash
joblist='job_list.txt'
njobs=`wc ${joblist} | awk '{print $1}'`
cwd=`pwd`
while IFS= read -r line
do
folder="$line" #`awk '(NR=='${i}'){print}' ${joblist}`
echo $folder
cd ${folder}
if [ -f out.txt ]
then
echo out.txt found in $folder
fi
cd ${cwd}
done < job_list.txt
이게 도움이 되길 바란다. 조금 더 쉽습니다... line=current-line-from'job_list.txt'
한 줄씩 읽으므로 파일은 다음과 같습니다.
folder1
folder2
folder234
내 결과:
france1@macubuntu:/tmp/tmdf$ bash script.sh
folder1
folder2
folder234
out.txt found in folder234
france1@macubuntu:/tmp/tmdf$
제가 도움이 되었기를 바랍니다...
답변3
zsh
대신 이것을 사용하겠습니다 bash
.
#! /bin/zsh -
joblist='job_list.txt'
dirs=( ${(f)"$(<$joblist)"} )
for dir in $dirs; do
first_out=( $dir/**/out.txt(NDY1) )
if (( $#first_out )); then
print -r out.txt found in $dir
fi
done
bash
다른 GNU의 경우에는 find
다음과 같습니다.
#! /bin/bash -
joblist='job_list.txt'
dirs=(); readarray -t dirs < "$joblist"
for dir in "${dirs[@]}"; do
[[ -n $dir ]] || continue
[[ $dir = [/.]* ]] || dir=./$dir
first_out=$(find "$dir" -name out.txt -print -quit)
if [[ -n $first_out ]]; then
printf '%s\n' "out.txt found in $dir"
fi
done
몇 가지 참고사항:
readarray -t lines < file
파일의 행을 배열로 저장하는 것도 가능하지만,file
열 수 없는 경우에는readarray
실행조차 되지 않아$dirs
설정도 되지 않으므로 미리 변수를 초기화하는 것이 중요하다는 점에 유의하세요.bash
마지막으로**/
zsh 스타일 재귀 와일드카드( ) 옵션에 대한 지원이 추가되었습니다globstar
. 그러나 여전히 심볼릭 링크 처리(버전 간 동작 변경)와 관련된 몇 가지 문제가 있으며, 더 중요한 것은 이 경우 사용된 목록을 정렬하지 않고도 forN
,nullglob
forD
또는 첫 번째 일치 시dotglob
중지 와 같은 glob 한정자에 대한 지원을 추가하지 않는다는 것입니다.Y1
위에.find
find "$dir"
로 시작 하면$dir
중단됩니다-
. 옵션 끝 표시find
에 대한 지원이 실제로 지원되지만 , 로 시작하는 인수는 옵션이 아닌 경우(예: , 또는 ) 여전히 조건자로 처리되기 때문에 여기서는 도움이 되지 않습니다. 그렇기 때문에 절대값 이 아니고 아직 시작하지 않는 s를 앞에 붙이는 것입니다 (그래서 가 됩니다 ). BSD는 이 문제 방지를 지원 하지만 GNU는 아직 지원하지 않습니다 .--
-
(
)
!
./
$dir
.
-my-annoying-dir-
./-my-annoying-dir-
find
find -f "$dir"
find
- 최소한 하나라도 존재하는지 확인하려는 경우에는
out.txt
모두 찾을 필요가 없습니다 . 첫 번째 게임에서 멈출 수 있습니다. 따라서 (GNU에 따라)-quit
(일부 BSD에는-exit
이에 대한 규정이 있습니다). - zsh는
${(f)"$(<file)"}
개행으로 분할되지만 따옴표가 없으면 빈 요소가 제거됩니다(그렇지 않은 경우$dirs
아래에서 따옴표가 없는 다음 요소가 해당 요소를 제거합니다). 빈 경로는 일반적으로 유효한 경로가 아니므로 오류가 발생해야 하지만 와 연결되면/something
성가시게도 유효할 수 있는 관련 없는 절대 경로로 변합니다. 앞에 오면./
현재 디렉토리가 됩니다. 따라서 여기서는 건너뛰는 것이 더 낫습니다. 따라서[[ -n $dir ]] || continue
bash 변형입니다.