if 조건에서 find 명령을 작성하려고 합니다. 먼저 요구 사항을 공유하겠습니다. /tmp/fmxfile이라는 파일에 파일 목록이 있습니다.
cat /tmp/fmxfile
/fmx/eng/hint.fmx
/pll/case.pll
/plx/eng/case.plx
첫 번째 IF 조건에서 먼저 파일 위에 for 루프를 작성하고 있습니다(조건이 통과하면 다른 경로에서 모든 파일 찾기). 파일이 해당 경로에 있는지 두 번째 IF 조건에 없는지 확인하고 싶습니다. 지난 5분 동안 파일이 수정되었는지 확인하고, true인 경우 파일을 /tmp 경로에 복사합니다.
cd /apps/common/bau/base/
for file in `cat /tmp/fmxfileslist`
do
if [ -f $file ]
then
echo "File '${file}' found in $(pwd) path and created on $(date +%D)."
if [ $(find $file -mmin -5 -type f) ="true" ];
then
cp -a $file /tmp/basefmxfiles
ls -lrt | grep /tmp/basefmxfiles
else
echo "But the file is not modified in last 5 minutes"
fi
else
echo "$0: File '${file}' not found."
fi
done
답변1
코드에 대한 몇 가지 설명( sh
구문에 있다고 가정):
cd /apps/common/bau/base/
종료 상태를 확인하지 않으므로 cd
실패하면 현재 작업 디렉토리에서 나머지 스크립트를 계속 실행합니다.
for file in `cat /tmp/fmxfileslist`
더 이상 사용되지 않는 명령 대체 형식 위에 분할+glob을 사용하며 `...`
파일 행을 반복하려는 것처럼 보이지만 구문은 다음과 같습니다.
while IFS= read -r file <&3; do
...
done 3< /tmp/fmxfileslist
(또는 변경해야 합니까 /tmp/fmxfile
)?
/tmp
또한 전역적으로 쓰기 가능한 디렉터리에서 고정된 이름(예:)을 가진 파일을 사용하는 것은 보안 관점에서 나쁜 습관입니다.
또한 예제 목록의 경로 중 어느 것도 상대 경로가 아니므로 현재 작업 디렉터리가 무엇인지가 중요합니까? 또는 목록은 다음과 같아야 합니다.
fmx/eng/hint.fmx
pll/case.pll
plx/eng/case.plx
대신에? 아니면 앞에 선행을 /
제거하거나 삽입해야 합니까?.
do if [ -f $file ]
이것은 확장에서 다시 분할+glob을 사용하는 것인데 $file
, 이는 말이 되지 않습니다. 아마도 당신이 의미하는 것은 [ -f "$file" ]
파일이 존재하는지 확인하는 것이 목적인지, 파일에 액세스할 수 있고 다음으로 식별될 수 있는지 여부입니다.정기적인(디렉토리, fifo, 장치, 소켓이 아님...) 심볼릭 링크 확인 후.
then echo "File '${file}' found in $(pwd) path and created on $(date +%D)."
$(pwd)
이번에는 최신 형태의 명령 대체를 사용하여 $PWD
POSIX 쉘에 작성하는 것이 가능합니다. date +%D
현재 날짜를 인쇄합니다. $file
GNU를 가정하여 마지막 수정 시간을 인쇄하려면 date
이 옵션을 사용할 수 있습니다 -r
. %D
제공된 날짜 형식은 mm/dd/yy
매우 모호하며 시간이나 시간대 정보를 제공하지 않습니다. $(date -r "$file" +%FT%T%z || echo UNKNOWN)
.
또한 echo
임의의 데이터에는 사용할 수 없습니다. 대신 사용하십시오 printf '%s\n' "..."
.
if [ $(find $file -mmin -5 -type f) ="true" ];
$file
이번에도 sum 의 출력에 Split+glob을 사용하세요 find
. 또한 공백이 누락되어 =
명령 에 비교 연산자 인수가 [
표시되지 않고 =
대신 가짜 =true
인수가 표시됩니다.
또한, find
찾은 파일 경로를 인쇄하므로 다음과 같은 경우에만 인쇄합니다 ( true
뒤에 오는 개행 문자는 명령 대체에 의해 제거되므로 여러 개의 개행 문자도 작동하지만 가끔 파일의 한 줄을 읽을 때, 이런 일은 일어나지 않습니다. 파일에 임의의 파일 이름이 포함될 수 없습니다.$file
true
true
fmxfileslist
fmxfileslist
find
또한 (on, ...)로 시작하는 파일 이름은 차단을 유발한다는 점에 유의하세요 .-
!
(
-type f
일반 파일에 대한 심볼릭 링크 의 경우 false를 반환하는 반면, [ -f "$file" ]
위의 내용은 true를 반환합니다. -xtype f
둘 사이의 일관성을 위해 또는 -L
심볼릭 링크 대상의 수정 시간을 확인하기 위해(역시 ) 특정 GNU가 필요하므로 date -r
GNU find
4.9 이상을 가정합니다.
if [ "$(
printf '%s\0' "$file" | find -L -files0-from - -prune -type f -mmin -5 -printf true)" = true ]
then
printf '%s\n' "$file is found to be regular after symlink resolution and has been last modified within the last 5 minutes or in the future"
fi
find
-files0-from -
여기서 NUL로 구분된 파일 경로는 위에서 언급한 질식 문제를 피하기 위한 인수가 아닌 stdin(거기에서 가져오며 4.9 이상이 필요함)으로 전달됩니다 .
then cp -a $file /tmp/basefmxfiles
--
다시 말하지만, 분할+글로브는 의미가 없으며 옵션 구분 기호도 누락되었습니다 . 미리 디렉터리가 없으면 /tmp/basefmxfiles
복사본으로 생성되므로 이를 방지하려면 대상 디렉터리 끝에 $file
a 를 추가하는 것이 좋습니다 (또는 여기서는 이미 GNUisms를 사용하고 있으므로 GNU 옵션을 사용합니다). :/
cp
-t
cp -a -- "$file" /tmp/basefmxfiles/
cp -at /tmp/basefmxfiles -- "$file"
ls -lrt | grep /tmp/basefmxfiles
ls -lrt
현재 작업 디렉토리(여기에 있어야 함)의 내용을 나열하고 /apps/common/bau/base/
이를 출력에 포함하는 유일한 방법은 /tmp/basefmxfiles
다음과 같은 경우입니다.
lrwxrwxrwx 1 user group 1 May 17 18:11 somelink -> foo/tmp/basefmxfilesbar
심볼릭 링크가 있으므로 이 명령으로 무엇을 하려는지 명확하지 않습니다.
else echo "But the file is not modified in last 5 minutes" fi else echo "$0: File '${file}' not found."
여부를 확인하는 else
부분 입니다 .[ -f $file ]
$file
정기적인파일이므로 오류(stderr로 이동해야 함)는 다음과 같아야 합니다.
printf>&2 '%s\n' "$0: File '$file' not found as a regular file."
여기에서 다음 명령을 사용하여 모든 작업을 수행할 수 있습니다 find
(역시 GNU find
4.9 이상이라고 가정).
cd /apps/common/bau/base || exit
tr '\n' '\0' < /tmp/fmxfileslist |
find -L -files0-from - \
-prune \
-type f \
-printf '%p regular and last modified on %TFT%TT%Tz\n' \
'(' \
-mmin -5 -printf '%p regular and mtime > -5min\n' -o \
-printf '%p regular but older\n' \
')' -o -printf '%p not a regular files\n'
액세스할 수 없는 파일의 경우 find
stderr에 오류 메시지를 인쇄합니다.
zsh
또는 대신 사용할 수 있습니다 sh
.
#! /bin/zsh -
cd /apps/common/bau/base || exit
files=( ${(f)"$(</tmp/fmxfileslist)"} )
regulars=( $^files(N-.) )
recent_regulars=( $^regulars(N-m-5) )
older_regulars=( ${regulars:|recent_regulars} )
non_regulars=( ${files:|regulars} )
accessible=( $^files(N-^@) )
inaccessible=( ${files:|accessible} )
예를 들어, print
이러한 배열의 내용은 열에 대해 경외감을 r
느끼 거나 반복됩니다 (zsh에는 인용되지 않은 매개변수 확장을 위한 분할+글로브가 없으므로 인용되지 않은 상태로 둘 수 있습니다).1
C
print -rC1 -- $array
for file ($array) something with $file
심볼릭 링크 확인 전후에 파일의 마지막 수정 시간을 얻으려면 stat
내장 기능을 사용할 수 있습니다.
zmodload zsh/stat
stat -F %FT%T%z -H after -- $file &&
stat -LF %FT%T%z -H before -- $file &&
print -r "mtime before symlink resolution: $before[mtime]; after: $after[mtime]"
¹ BSD에서는 이 구문을 대신 사용할 수 있습니다 find -f "$file" ...
.