development

Git을 사용하여 저장소에서 일치하는 파일 이름을 검색 할 수 있습니까?

big-blog 2020. 11. 6. 21:04
반응형

Git을 사용하여 저장소에서 일치하는 파일 이름을 검색 할 수 있습니까?


Git 저장소의 여러 하위 디렉토리에 "HelloWorld.pm"파일이 있다고 말하면됩니다.

"HelloWorld.pm"과 일치하는 모든 파일의 전체 경로를 찾는 명령을 실행하고 싶습니다.

예를 들면 :

/path/to/repository/HelloWorld.pm
/path/to/repository/but/much/deeper/down/HelloWorld.pm
/path/to/repository/please/dont/make/me/search/through/the/lot/HelloWorld.pm

Git을 사용하여 주어진 파일 이름과 일치하는 모든 전체 경로를 효율적으로 찾는 방법은 무엇입니까?

Linux / Unix find 명령으로이 작업을 수행 할 수 있다는 것을 알고 있지만 파일 이름의 인스턴스를 찾는 모든 하위 디렉터리를 검색하는 것을 피하고 싶었습니다.


git ls-files저장소에있는 모든 파일의 목록을 제공합니다. 패턴을 전달하여 해당 패턴과 일치하는 파일을 가져올 수 있습니다.

git ls-files '*/HelloWorld.pm'

파일 세트를 찾고 내용을 통해 grep하려면 다음을 사용하여 수행 할 수 있습니다 git grep.

git grep some-string -- '*/HelloWorld.pm'

음, 원래 질문은 저장소에 관한 것이 었습니다. 저장소에는 두 개 이상의 커밋이 포함되어 있지만 (적어도 일반적인 경우) 검색 전에 제공된 답변은 하나의 커밋을 통해서만 제공됩니다.

전체 커밋 기록을 실제로 검색하는 답을 찾을 수 없었기 때문에 거의 모든 커밋을 고려하는 빠른 무차별 대입 스크립트 git-find-by-name을 작성했습니다.

#! /bin/sh
tmpdir=$(mktemp -td git-find.XXXX)
trap "rm -r $tmpdir" EXIT INT TERM

allrevs=$(git rev-list --all)
# well, nearly all revs, we could still check the log if we have
# dangling commits and we could include the index to be perfect...

for rev in $allrevs
do
  git ls-tree --full-tree -r $rev >$tmpdir/$rev 
done

cd $tmpdir
grep $1 * 

더 우아한 방법이있을 수 있습니다.

매개 변수가 grep에 전달되는 사소한 방법에 유의하십시오. 따라서 파일 이름의 일부와 일치합니다. 이것이 원하지 않는 경우 검색 표현식을 앵커하거나 적절한 grep 옵션을 추가하십시오.

깊은 역사의 경우 출력이 너무 시끄러울 수 있습니다. git rev-list가 할 수있는 것과는 반대로 개정 목록을 범위로 변환하는 스크립트에 대해 생각했습니다. 그러나 지금까지 그것은 생각으로 남아 있습니다.


시험:

git ls-tree -r HEAD | grep HelloWorld.pm

git ls-files | grep -i HelloWorld.pm

grep -i는 grep 대소 문자를 구분하지 않습니다.


[이건 약간의 댓글 남용입니다. 인정하지만 아직 댓글을 달 수 없으며 @ uwe-geuder의 답변을 개선 할 것이라고 생각했습니다.]

#!/bin/bash
#
#

# I'm using a fixed string here, not a regular expression, but you can easily
# use a regular expression by altering the call to grep below.
name="$1"

# Verify usage.
if [[ -z "$name" ]]
then
    echo "Usage: $(basename "$0") <file name>" 1>&2
    exit 100
fi  

# Search all revisions; get unique results.
while IFS= read rev
do
    # Find $name in $rev's tree and only use its path.
    grep -F -- "$name" \
        <(git ls-tree --full-tree -r "$rev" | awk '{ print $4 }')
done < \
    <(git rev-list --all) \
    | sort -u

다시 한 번 @ uwe-geuder에 +1하여 훌륭한 답변을 얻으십시오.

BASH 자체에 관심이있는 경우 :

당신이 (이 같은 배열을 사용할 때 같이 for 루프의 단어 분할의 보장하지 않는 한 for item in "${array[@]}"), 나는 높게 사용하는 것이 좋습니다 while IFS= read var ; do ... ; done < <(command)당신이 이상 반복하고 명령 출력은 줄 바꿈 (또는에 의해 분리 될 때 read -d''출력에 의해 분리 될 때 null 문자열 $'\0'). git rev-list --all40 바이트 16 진수 문자열 (공백 없음)을 사용 하는 것이 보장 되지만 기회를 잡는 것을 좋아하지 않습니다. 이제 git rev-list --all명령을 라인을 생성 하는 명령으로 쉽게 변경할 수 있습니다.

또한 기본 제공 BASH 메커니즘을 사용하여 임시 파일 대신 입력 및 필터 출력을 주입하는 것이 좋습니다.


The script by Uwe Geuder (@uwe-geuder) is great but there really is no need to dump each of the ls-tree outputs in its own directory, unfiltered.

Much faster and using less storage: Run the grep on the output and then store it, as shown in this gist

참고URL : https://stackoverflow.com/questions/277546/can-i-use-git-to-search-for-matching-filenames-in-a-repository

반응형