source

최신 파일 일치 패턴을 찾기 위한 Bash 기능

ittop 2023. 5. 27. 11:57
반응형

최신 파일 일치 패턴을 찾기 위한 Bash 기능

Bash에서는 특정 패턴과 일치하는 최신 파일의 파일 이름을 반환하는 함수를 만들고 싶습니다.예를 들어 다음과 같은 파일 디렉토리가 있습니다.

Directory/
   a1.1_5_1
   a1.2_1_4
   b2.1_0
   b2.2_3_4
   b2.3_2_0

저는 'b2'로 시작하는 최신 파일을 원합니다.bash에서 이걸 어떻게 하나요?이것을 내 안에 가지고 있어야 합니다.~/.bash_profile대본.

ls명령에 매개 변수가 있습니다.-t시간별로 정렬합니다.그런 다음 첫 번째(가장 최근의) 항목을 사용할 수 있습니다.head -1.

ls -t b2* | head -1

하지만 조심하세요:ls의 출력을 구문 분석하면 안 되는 이유

제 개인적인 의견: 파싱ls파일 이름에 공백이나 줄 바꿈과 같은 재미있는 문자가 포함될 수 있는 경우 위험합니다.

파일 이름에 재미있는 문자가 포함되지 않도록 보장할 수 있는 경우(파일 생성 방법을 제어하기 때문일 수 있음) 구문 분석ls꽤 안전합니다.

다양한 상황에서 많은 사람이 여러 시스템에서 실행해야 하는 스크립트를 개발하는 경우 구문 분석하지 마십시오.ls.

안전한 방법은 다음과 같습니다.디렉토리에서 최신(최신, 가장 빠른, 가장 오래된) 파일을 찾는 방법은 무엇입니까?

unset -v latest
for file in "$dir"/*; do
  [[ $file -nt $latest ]] && latest=$file
done

의 조합find그리고.ls에 적합한

  • 줄 바꿈 없이 파일 이름
  • 파일의 양이 많지 않음
  • 그다지 길지 않은 파일 이름

해결책:

find . -name "my-pattern" -print0 |
    xargs -r -0 ls -1 -t |
    head -1

그것을 분해해 보겠습니다.

와 함께find다음과 같은 모든 흥미로운 파일을 일치시킬 수 있습니다.

find . -name "my-pattern" ...

그 다음에 사용-print0우리는 모든 파일 이름을 안전하게 전달할 수 있습니다.ls다음과 같이:

find . -name "my-pattern" -print0 | xargs -r -0 ls -1 -t

추가의find검색 매개 변수 및 패턴을 여기에 추가할 수 있습니다.

find . -name "my-pattern" ... -print0 | xargs -r -0 ls -1 -t

ls -t파일을 수정 시간별로 정렬하고(먼저 정렬) 한 줄에 하나씩 인쇄합니다.사용할 수 있습니다.-c생성 시간을 기준으로 정렬합니다.참고: 새 줄이 포함된 파일 이름으로 구분됩니다.

마침내.head -1정렬된 목록의 첫 번째 파일을 가져옵니다.

참고: xargs인수 목록의 크기에 대한 시스템 제한을 사용합니다.이 크기가 초과되면,xargs부를 것입니다ls여러 번이렇게 하면 정렬이 중단되고 최종 출력도 중단될 수 있습니다.달려.

xargs  --show-limits

시스템의 제한을 확인합니다.

참고 2: 사용find . -maxdepth 1 -name "my-pattern" -print0하위 폴더를 통해 파일을 검색하지 않으려는 경우

참고 3: @starfri가 지적한 바와 같이 --r을 지지하는 주장.xargs의 통화를 막고 있습니다.ls -1 -t일치하는 파일이 없는 경우find제안 감사합니다.

필요한 Bash 기능을 구현할 수 있습니다.

# Print the newest file, if any, matching the given pattern
# Example usage:
#   newest_matching_file 'b2*'
# WARNING: Files whose names begin with a dot will not be checked
function newest_matching_file
{
    # Use ${1-} instead of $1 in case 'nounset' is set
    local -r glob_pattern=${1-}

    if (( $# != 1 )) ; then
        echo 'usage: newest_matching_file GLOB_PATTERN' >&2
        return 1
    fi

    # To avoid printing garbage if no files match the pattern, set
    # 'nullglob' if necessary
    local -i need_to_unset_nullglob=0
    if [[ ":$BASHOPTS:" != *:nullglob:* ]] ; then
        shopt -s nullglob
        need_to_unset_nullglob=1
    fi

    newest_file=
    for file in $glob_pattern ; do
        [[ -z $newest_file || $file -nt $newest_file ]] \
            && newest_file=$file
    done

    # To avoid unexpected behaviour elsewhere, unset nullglob if it was
    # set by this function
    (( need_to_unset_nullglob )) && shopt -u nullglob

    # Use printf instead of echo in case the file name begins with '-'
    [[ -n $newest_file ]] && printf '%s\n' "$newest_file"

    return 0
}

기본 제공되는 Bash만 사용하며 이름에 줄이나 다른 비정상적인 문자가 포함된 파일을 처리해야 합니다.

find 명령을 사용합니다.

4하면 Bash 4.2+를 사용합니다.-printf '%T+ %p\n'파일 타임스탬프 값입니다.

find $DIR -type f -printf '%T+ %p\n' | sort -r | head -n 1 | cut -d' ' -f2

예:

find ~/Downloads -type f -printf '%T+ %p\n' | sort -r | head -n 1 | cut -d' ' -f2

더 유용한 스크립트는 다음 웹 사이트에서 찾을 수 있는 스크립트를 참조하십시오.

사용할 수 있습니다.stat전면에 파일 시간이 추가된 파일 글러브와 데코레이션:

$ stat -f "%m%t%N" b2* | sort -rn | head -1 | cut -f2-

코멘트에 명시된 바와 같이, 최고의 크로스 플랫폼 솔루션은 Python, Perl, Ruby 스크립트를 사용하는 것일 수 있습니다.

그런 점에서 루비는 작고 버리는 스크립트를 쓰는 것처럼 매우 어색하지만 명령 줄에서 바로 파이썬이나 펄의 힘을 가지고 있기 때문에 사용하는 편입니다.

여기 루비가 있습니다.

ruby -e '
# index [0] for oldest and [-1] for newest
newest=Dir.glob("*").
    reject { |f| File.directory?(f)}.
    sort_by { |f| File.birthtime(f) rescue File.mtime(f) 
    }[-1]
p newest'

그러면 현재 작업 디렉터리에 있는 최신 파일이 만들어집니다.

또한 다음을 사용하여 글로벌을 재귀적으로 만들 수 있습니다.**/*glob " 또일치는파제한다니합일로는하다▁with"로 일치하는 파일로 합니다.b2*,주요사항

패턴과 일치하는 디렉토리에서 최신 파일을 찾기 위한 Bash 함수

#1.  Make a bash function:
newest_file_matching_pattern(){ 
    find $1 -name "$2" -print0 | xargs -0 ls -1 -t | head -1  
} 
 
#2. Setup a scratch testing directory: 
mkdir /tmp/files_to_move;
cd /tmp/files_to_move;
touch file1.txt;
touch file2.txt; 
touch foobar.txt; 
 
#3. invoke the function: 
result=$(newest_file_matching_pattern /tmp/files_to_move "file*") 
printf "result: $result\n"

인쇄:

result: /tmp/files_to_move/file2.txt

또는 파이썬 인터프리터에 하청을 주는 취약한 바쉬샵 트릭이 당신의 각도에 더 가깝다면, 이것은 동일한 작업을 수행합니다.

#!/bin/bash 
 
function newest_file_matching_pattern { 
python - <<END 
import glob, os, re  
print(sorted(glob.glob("/tmp/files_to_move/file*"), key=os.path.getmtime)[0]); 
END 
} 
 
result=$(newest_file_matching_pattern) 
printf "result: $result\n" 

인쇄:

result: /tmp/files_to_move/file2.txt

이름한 파일이 등)\n문자는 이런 종류의 구문 분석을 혼란스럽게 만들 수 있습니다.Perl로 실행하는 방법은 다음과 같습니다.

perl -le '@sorted = map {$_->[0]} 
                    sort {$a->[1] <=> $b->[1]} 
                    map {[$_, -M $_]} 
                    @ARGV;
          print $sorted[0]
' b2*

이것은 슈바르츠식 변형입니다.

Google 사용자:

ls -t | head -1

  • -t합니다.
  • head -1 번째 합니다.

(운영 환경에서 사용 안 함)

이것을 달성하는 훨씬 더 효율적인 방법이 있습니다.다음 명령을 고려합니다.

find . -cmin 1 -name "b2*"

이 명령은 "b2*"에서 와일드카드 검색으로 정확히 1분 전에 생성된 최신 파일을 찾습니다.지난 이틀 동안의 파일을 원한다면 아래 명령을 사용하는 것이 좋습니다.

find . -mtime 2 -name "b2*"

"."는 현재 디렉토리를 나타냅니다.이게 도움이 되길 바랍니다.

언급URL : https://stackoverflow.com/questions/5885934/bash-function-to-find-newest-file-matching-pattern

반응형