저는 애플리케이션을 작성 중이며 전제 조건 중 하나는 여러 디렉터리를 조사하고 각 파일의 최신 버전을 찾을 수 있어야 한다는 것입니다.
최신 파일을 성공적으로 사용 ls
하고 가져왔지만 동일한 파일이 여러 디렉터리에 있는 경우 각 파일의 최신 버전이 아닙니다. find
한 가지 주목할 점은 파일 이름을 반드시 알 수는 없지만 디렉터리 이름은 알 수 있다는 것입니다.
예:DIR1, DIR2 및 DIR3에는 각각 FileA 및 FileB 버전이 포함되어 있습니다. 세 개 이상의 디렉터리에 모두 포함된 최신 버전의 FileA 및 FileB가 필요합니다.
누구든지 아이디어가 있나요?
답변1
올바른 도구를 선택하셨습니다.
ls -t
파일을 시간별로 정렬하여 최신 파일을 선택할 수 있는 좋은 방법입니다.find
디렉터리 및 하위 디렉터리에서 특정 패턴과 일치하는 파일을 찾는 데 적합한 도구입니다.
물론 까다로운 부분은 파일 이름별로 일종의 그룹화가 필요하고 각 그룹에서 최신 파일을 선택해야 한다는 것입니다. 이러한 요구 사항으로 인해 최신 버전을 찾기 위해 각 대상 파일 이름을 반복하는 루프가 필요하다고 생각합니다.
파일이 또는 에 있다고 가정하면 $dir1
다음 $dir2
과 $dir3
같이 일부 스키마의 최신 버전을 찾는 함수를 작성할 수 있습니다.
find_latest() {
pattern=$1
ls -t "$dir1/$pattern" "$dir2/$pattern" "$dir3/$pattern" | head -n 1
}
그런 다음 패턴 이 있다고 가정하면 access.log
다음 과 같이 반복할 수 있습니다.error.log
x*
for pattern in access.log error.log 'x*'; do
latest=$(find_latest 'a*')
echo $latest
done
위의 가정이 유지되지 않고 파일이 $dir1
, 또는 $dir2
의 하위 디렉터리에 있을 수 있는 경우 를 $dir3
사용해야 하면 find
조금 더 복잡해집니다.
find_latest() {
pattern=$1
find "$dir1" "$dir2" "$dir3" -name "$pattern" -print0 | xargs -0 ls -t | head -n 1
}
작은 주의 사항이 있습니다. 이 head -n 1
단계에서는 경로에서 개행 문자 뒤의 부분이 잘리기 때문에 경로에 개행 문자가 포함되어 있으면 이 함수가 제대로 작동하지 않습니다. 그런 길이 없기를 기도합니다 ;-)
답변2
다음과 같은 방법으로 이 작업을 수행할 수 있습니다 pax
.
pax -wrtvZs"|.*/||p" ./DIR[123] "$PWD"
그래서 나는 그것을 논쟁으로 분해하려고 노력할 것입니다:
-wr
-w
rite와r
ead는 함께pax
파일을 보관하기보다는 복사해야 함을 의미합니다. 복사본을 버리고-l
.-t
pax
- 메타데이터를 확인하기 위해 파일을 읽기 전의 상태로 모든 파일 액세스 시간을 재설정합니다.-v
- 작업 시간이 깁니다.-Z
- 소스 파일의 수정 시간은 가능한 모든 이름 교체가 완료될 때까지 비교되지 않습니다.- 그것은 이것입니다(그리고 다음에 나올 내용)이렇게 하면 모든 것이 매우 쉬워집니다. 이것이 없으면 - 그리고 아마도 다른 곳에서 직면하게 될 문제는 - 기본 이름을 공유하더라도
DIR1/FILEA
다른 파일입니다.DIR2/FILEA
그러니까 이게 없으면 절대 비교가 안 되겠죠...
- 그것은 이것입니다(그리고 다음에 나올 내용)이렇게 하면 모든 것이 매우 쉬워집니다. 이것이 없으면 - 그리고 아마도 다른 곳에서 직면하게 될 문제는 - 기본 이름을 공유하더라도
-s
- 파일 이름의 일부를 표준 정규식으로 바꿉니다sed
.- 여기서는 각 파일의 모든 부분을 기본 이름으로 줄였습니다
-Z
.모두FILEA
s로 변경하고 최신 내용만"$PWD"
.
- 여기서는 각 파일의 모든 부분을 기본 이름으로 줄였습니다
나는 이 모든 것을 확인하기 위해 다음 테스트를 사용합니다.
for d in DIR3 DIR1 DIR2
do cd ~; mkdir -p "$d"; cd "$d"
sleep 90; touch FILEB FILEA
done; cd ~
...테스트 세트를 가져옵니다. 최종 수정 시간은 다음과 같습니다.
ls -l ./DIR[123]/FILE[AB]
-rw-r--r-- 1 mikeserv mikeserv 0 Dec 20 03:28 ./DIR1/FILEA
-rw-r--r-- 1 mikeserv mikeserv 0 Dec 20 03:28 ./DIR1/FILEB
-rw-r--r-- 1 mikeserv mikeserv 0 Dec 20 03:29 ./DIR2/FILEA
-rw-r--r-- 1 mikeserv mikeserv 0 Dec 20 03:29 ./DIR2/FILEB
-rw-r--r-- 1 mikeserv mikeserv 0 Dec 20 03:26 ./DIR3/FILEA
-rw-r--r-- 1 mikeserv mikeserv 0 Dec 20 03:26 ./DIR3/FILEB
그래서 내가 실행할 때 :
pax -wrtvZs"|.*/||p" ./DIR[123] "$PWD"
ls -l ./FILE[AB]
...출력은...
./DIR1/FILEA >> FILEA
/home/mikeserv/FILEA
./DIR1/FILEB >> FILEB
/home/mikeserv/FILEB
./DIR2/FILEA >> FILEA
/home/mikeserv/FILEA
./DIR2/FILEB >> FILEB
/home/mikeserv/FILEB
./DIR3/FILEA >> FILEA
./DIR3/FILEB >> FILEB
-rw-r--r-- 1 mikeserv mikeserv 0 Dec 20 03:29 ./FILEA
-rw-r--r-- 1 mikeserv mikeserv 0 Dec 20 03:29 ./FILEB
당신은 그것이 일어나는 것을 볼 수 있습니다. -s|||p
파일 이름이 변경 되면 p
수정자는 로 변경됩니다 stderr
. 따라서 DIR1
파일이 먼저 평가되어 에 복사된 $PWD
다음 DIR2
파일이 동일한 처리를 받지만 DIR3
파일은 $PWD/FILE[AB]
현재보다 최신이므로 복사되지 않습니다.