(폴더) 이름 목록을 처리하기 위한 Bash 스크립트

(폴더) 이름 목록을 처리하기 위한 Bash 스크립트

폴더 이름 목록이 포함된 텍스트 파일을 반복하고 해당 폴더 중 특정 경로(이 경우에는 2021.

내 list.txt 파일에는 다음과 같은 목록이 포함되어 있습니다.

100001
100002
100003
100004
...

2021이름을 확인하려는 하위 폴더가 포함된 디렉터리(소위)가 있습니다.

100001
100002
100004
...

이제 이 예에서 스크립트는 폴더가 100003누락되었음을 나타내야 합니다. 이 스크립트의 목적은 단순히 텍스트 파일에 나열된 폴더가 경로에서 누락되었는지 찾는 것입니다.

지금까지 나는 다음을 가지고 있습니다 :

while IFS= read -r line; do
    if [[ ! -d "2021/$line" ]]; then
        echo $line is missing
    fi
done <<< $(cat list.txt)

하지만 이 코드는 디렉토리에 있는 모든 폴더를 인쇄할 뿐이 2021므로 명령문에 문제가 있는 것으로 추측되지만 IF알 수 없습니다.

답변1

폴더가 포함된 경로 외부에서 쉘 스크립트를 실행하고 있다고 가정합니다 2021.
다음과 같은 구조로:

$> tree
#output: 
.
├── 2021
│   ├── 100000
│   ├── 100001
│   ├── 100002
│   ├── 100003
│   ├── 100006
│   ├── 100007
│   ├── 100008
│   ├── 100009
│   ├── 100010
│   ├── 100011
│   ├── 100019
│   ├── 100020
├── list.txt
└── script

아무것도 변경하지 않고 현재 스크립트를 실행할 수 있어야 합니다. 다음을 사용하세요../script

문제는 script스크립트 디렉토리 외부에서 코드를 실행하면 코드가 성공적으로 실행되지 않는다는 것입니다. 따라서 스크립트를 다음과 같이 변경하는 것이 좋습니다.

#!/bin/bash

filepath="$(dirname $(readlink -f $0) )"
cd $filepath

while read -r line; do
    if [[ ! -d "2021/$line" ]]; then
        echo $line is missing
    fi
done <<< $(cat list.txt)
#Or:
#  done < /paht/to/list.txt

나는 그것을 삭제했다 IFS=. 왜 가지고 있는지는 모르겠지만 꼭 사용해야 한다면 추가하세요.

따라서 모든 디렉터리에서 스크립트를 실행할 수 있습니다../path/to/dir/script


다음 명령을 사용하여 누락된 디렉터리를 가져올 수도 있습니다.

#With this code you will get only the missing dirs. The text 'is missing'
#won't appear here
diff --new-line-format="" --unchanged-line-format=""  <(sort /path/to/list.txt)  <(find . -maxdepth 1 -type d ! -path . -printf '%P\n' | sort)

파일이 실제로 정렬된 경우 단순으로 list.txt변경할 수 있습니다.<(sort /path/to/list.txt)/path/to/list.txt

2021위의 코드를 사용하는 경우 디렉토리 아래에 배치 하고 /path/to/list.txt실제 경로로 변경하십시오.list.txt

답변2

몇 시간 동안 문제를 검색한 끝에 마침내 해결책을 찾았습니다.

문제는 파일이 원래 Windows OS에서 생성된 다음 bash 쉘에서 사용된다는 것입니다. 즉, Windows에서는 줄 바꿈과 캐리지 리턴으로 끝나지만 Unix에서는 단일 줄 바꿈으로만 끝납니다.

IF따라서 파일의 이름을 폴더의 이름과 비교할 때 목록 파일의 이름에 누구에게도 표시되지 않는 추가 캐리지 리턴이 있기 때문에 분명히 일치하는 것이 불가능하다고 추측합니다 .

그래서 유닉스에서 파일을 다시 만들었고 이제 예상했던 결과를 완벽하게 얻었습니다. 도움을 주신 모든 분들께 감사드립니다.

답변3

저는 bash 대신 zsh를 사용합니다. 옵션으로 우수한 glob과 배열 연결( ${A:*B}) 및 빼기( ${A:|B}) 연산자를 사용할 수 있습니다.

#! /bin/zsh -
list=path/to/list.txt
dir=path/to/2021
# or list=${1?} dir=${2?}
# for instance to pass those as arguments to the script

expected=( ${(f)"$(<$list)"} )
# or expected=( ${(f)"$(dos2unix < $list)"} )
# if that file is in MS DOS/Windows format

got=( $dir/*(ND/:t) )
# or got=( $dir/*(ND-/:t) )
# to also consider symlinks to directories like your [[ -d ... ]] does

report() {
  if (( $# > 1 )); then
    print -rC1 -- $1: ' - '$^@[2,-1]
   else
    print -r   -- $1: none
  fi
}

report Found      ${expected:*got}
report Missing    ${expected:|got}
report Unexpected ${got:|expected}

관련 정보