지금까지 나는 이것을 가지고 있습니다 :
sudo find /path/to/dir -type f |
xargs -d "\n" sudo stat -c "%Y %n" |
{arithmetic to check if %Y is between 1685518962 and 1685624474??} |
{show file path}
참고로, 저는 알고 있지만 find -newermt
명령줄에서 산술을 수행하는 것에 대해 더 일반적으로 질문을 받습니다.
명확히하기 위해 나는 줄을 바랐습니다.
TCSH나 BASH도 괜찮지만, 다른 셸을 알려주시면 감사하겠습니다.
답변1
파일 목록을 처리하려면 NUL로 구분된 레코드( -print0
for find
, -0
for xargs
)를 사용하세요. 줄 바꿈은 파일 경로의 다른 문자(또는 문자가 아닌 문자)로 유효하기 때문입니다.
이미 GNU 확장을 사용하고 있으므로 다음을 수행할 수 있습니다.
sudo find /path/to/dir -type f '(' \
-newermt @1685518962 ! -newermt @1685624474 -exec something with {} + \
-o -exec something-else with {} + ')'
GNU 명령이 도입되기 오래 전에 GNU는 find
(더 나은 인터페이스를 통해) 파일에서 메타데이터를 보고할 수 있었습니다. stat
사후 처리의 경우 gawk/mawk, perl 또는 zsh와 같이 NUL로 구분된 레코드 및 부동 소수점 연산을 지원하는 도구를 사용할 수 있습니다.
sudo find -H /path/to/dir -type f -printf '%T@\0%p\0' |
LC_ALL=C gawk -v RS='\0' -F: '
{mtime = $0; getline file}
mtime > 1685518962 && mtime <= 1685624474 {
# something with mtime and file
}'
그리고 perl
:
sudo find -H /path/to/dir -type f -printf '%T@\0%p\0' | perl -0lne '
$mtime = $_; $file = <>;
if ($mtime > 1685518962 && $mtime <= 1685624474) {
# something with $mtime and $file
}'
여기에 제공된 예제를 포함한 모든 코드는 한 줄에 배치할 수 있습니다. 골프 연습이라면 perl
다음 중 가장 적합할 수 있습니다.
sudo find -H /path/to/dir -type f -printf '%p\0%T@\0'|perl -0lne'$m=<>;{...}if$m>1685518962&&$m<=1685624474'
또는 사용하는 경우 zsh
이러한 파일을 처리하는 데 쉘이 필요한 경우:
sudo find -H /path/to/dir -type f -printf '%T@/%p\0' |
while IFS=/ read -rd '' mtime file; do
(( mtime > 1685518962 && mtime <= 1685624474 )) &&
something with $mtime and $file
done
여전히 zsh
대부분의 기능이 내장되어 있지만 GNUism에 의존하지 않지만 아마도 속도가 느려지는 find
내장 기능 stat
(GNU 이전 버전 )도 있습니다.stat
sudo zsh -c '
zmodload zsh/stat
for file ( /path/to/dir/**/*(ND.) ) {
stat -LF %s.%N -A mtime +mtime -- $file &&
(( mtime > 1685518962 && mtime <= 1685624474 )) &&
something with $file and $mtime
}'
오늘날 나는 tcsh를 사용하여 안정적으로 작업을 수행하는 것이 거의 불가능하기 때문에 사용하지 않을 것입니다. 그러나 당신이 언급한 이후로 tcsh는 재귀 와일드카드를 지원한다는 점에 유의하십시오(2010년 bash 직후 zsh에서 복사됨). -파일의 mtime 검색을 지원하지만 1초 미만의 정밀도는 지원하지 않으며(산술은 어쨌든 정수만 가능합니다) 심볼릭 링크 확인 후에만 가능합니다.
set globstar globdot
foreach file ( /path/to/dir/** )
if ( -f $file:q && ! -l $file:q ) then
@ mtime = -M $file:q
if ( $mtime > 1685518962 && $mtime <= 1685624474 ) then
something with $file:q and $mtime
endif
endif
end
다른 사람들은 완전한 나노초 정밀도로 mtime을 얻는 반면, 부동 소수점 유형 및 // double
결과를 사용하는 대부분의 컴퓨터/C 컴파일러는 오늘날의 타임스탬프에 필요한 정밀도를 유지할 수 없습니다.awk
perl
zsh
예를 들어, 대부분은 마지막으로 수정된 파일이 어디에 있는지 보고하지 못합니다 1685518962.000000001
. 이는 귀하의 경우 큰 문제가 아닐 수 있습니다. 예를 들어 특정 마이크로초 내에 마지막으로 수정된 파일을 높은 정확도로 찾아야 하는 경우일 수 있습니다.
또한 참고: 환경 변수는 실행하는 명령에 sudo
전달되고 해당 변수에는 모든 인수가 포함되어 있으므로 실패할 수 있음을 의미합니다.SUDO_COMMAND
xargs sudo cmd
“인론이 너무 많다”execve()
파일 수가 많은 경우에는 매개 변수와 환경 문자열의 누적 크기가 제한되어 있기 때문에 오류가 발생하므로 을 xargs
실행할 수는 있지만 그 사이에 누적 크기가 두 배로 늘어나서 실행하지 못할 sudo
수도 있습니다 .sudo
cmd
이러한 이유와 sudo
몇 번의 호출을 실행하는 데 시간이 절약되므로 여기에서는 를 한 번만 호출 sudo xargs cmd
할 수도 있습니다.sudo
sudo sh -c '...'
¹ 이는 임의 정밀도 산술이 활성화된 경우 임의 정밀도 산술을 사용 하거나 더 일반적으로 초와 나노초를 개별적으로 비교하거나( 또는 shells/ 의 연산자가 수행할 수 있음) 숫자에 숫자를 사용하여 -MvPREC=100
최신 버전의 옵션으로 해결할 수 있습니다. 고정 크기 바이너리로 변환하는 대신 문자열 비교를 수행합니다(예: 숫자 정렬 매개변수 확장 플래그를 사용하는 대신 with 사용 ).gawk
-Mbignum
perl
-newertmt
[
-nt
() [[ $1 = ${${(n)@}[1]} ]] $t1 $t2
(( t1 < t2 ))
zsh
n
답변2
이것은 직업처럼 들립니다 awk
.
sudo find /path/to/dir -type f |
xargs -d "\n" sudo stat -c "%Y %n" |
awk '$1 > 1685518962 && $1 < 1685624474 {print}'
다음 옵션을 xargs
사용하여 삭제할 수 있습니다 .-execdir
find
sudo find /path/to/dir -type f -execdir stat -c "%Y %n" {} + |
awk '$1 > 1685518962 && $1 < 1685624474 {print}'
답변3
글쎄, bash는 허용됩니다.
#!/bin/bash
shopt -s dotglob globstar extglob nullglob
oldest=1685518962
newest=1685624474
for file in **/*; do
# check for regular file-ness
modtime=$(stat -c '%Y' -- "${file}")
[[ ( ! -L ${file} ) \
&& -f ${file} \
&& ( ${modtime} -gt ${oldest} ) \
&& ( ${modtime} -le ${newest} ) ]] \
&& {
# do stuff
}
done
Zsh는 globbing이 쉽게 할 수 있는 일에 있어서 조금 더 예쁘다
#!/usr/bin/zsh
zmodload zsh/stat
oldest=1685518962
newest=1685624474
for file in **/*(.ND); do
modtime=$(zstat -L +mtime -- "${file}")
[[ ${modtime} -gt ${oldest} \
&& ${modtime} -le ${newest} ]] \
&& {
# do stuff
}
done
네 문제 때문에문자 그대로산술을 요청하면 zsh와 bash 모두 확장에서 산술을 지원한다는 점을 지적하겠습니다. $(( ${modtime} - ${oldest} ))
하한 초 이후의 초 수를 알려줍니다. Zsh의 산술 기능은 특히 부동 소수점에서 약간 더 좋습니다.
답변4
다른 답변의 제안에도 불구하고일반적으로 말하면, 파이프라인에서 사용할 수 있는 한 줄 셸 산술 필터 함수를 생성하려면 두 명령을 결합해야 합니다.
xargs
입력 라인을 매핑하는 기능,sh
셸 산술 함수에 액세스
패턴으로xargs -L1 sh -c '_() { ... }; _ "$@"'
구체적인 예를 들어 보면 다음과 같습니다.
find ...
| xargs stat ...
| xargs -L1 sh -c '_() { [ 1685518962 -le $0 -a $0 -le 1685624474 ] && echo $@; }; _ "$@"'
이는 여기에 있는 것과 같은 빠르고 더러운 작업에 작동합니다. 그러나 데이터 볼륨이 있는 경우 와 같은 Map-Reduce 기능이 내장된 도구를 배포하고 싶을 것입니다 awk
.