묻다

묻다

묻다

저는 배쉬를 사용합니다. 파일을 찾을 때 일반적으로 다음을 수행합니다.

find -name stackexchange.hs

결과는 일반적으로 다음과 같습니다.

/youre/the/man/now/dog/stackexchange.hs
/you/are/no/longer/the/dog/dog/stackexchange.hs
/this/is/the/file/i/want/stackexchange.hs

그런 다음 다음 중 하나를 수행하고 싶습니다.

  • 옵션 1: 결과 목록의 마지막 항목 열기.
  • 옵션 2: 결과 목록에서 N번째 항목 열기.

현재는 잘라내기 및 붙여넣기에 마우스를 사용하고 있습니다. 이건 내 기억을 생각나게 해질문:

  1. 옵션 1과 2를 수행하는 간단한 한 줄 방법이 있습니까? 이런 일이 벌어지고 있으니 참고하세요뒤쪽에주문하다 find.
  2. 일종의 bash 벡터/배열로 stdout에서 N 줄을 캡처하는 방법이 있습니까?

이상적인 사용

$ find -name am_i_really_all_alone.txt
./borges/library/you_are_not_alone.txt
./borges/library/am_i_really_all_alone.txt
$ vim (N)

(구문과 의미는 다를 수 있지만 아이디어를 얻으실 수 있습니다)

유사점

비슷한 질문이 여러 개 있는 것 같습니다. 이 내 꺼야인지된차이점(저는 영감을 받을 수 있습니다):

당신의 도움을 주셔서 감사합니다! 제가 90년대 10대였을 때 *nix/BSD를 사용했는데 지치고 기분 나쁜 이웃이 플러그 앤 플레이 사운드 카드용 드라이버 설치를 도와달라고 전화해서 명령에 대해 논의하게 되어 기뻤습니다. - 세부 사항을 (분명히) 덜 무서운 개인과 연관시키십시오. 다시 돌아와서 기분이 너무 좋아요.

답변1

이는 귀하의 문제에 대한 잠재적인 해결책이며합리적으로펑키한 파일 이름이 있어도 (완전하지는 않지만) 안전합니다(개행 문자가 있는 파일 이름을 처리하지 않습니다. 아마도 수정할 수 있지만 다른 문제가 숨어 있을 수 있습니다).

두 개의 함수 중 첫 번째 함수는 find전달한 인수로 실행되고 출력을 배열에 저장하고 표시합니다. 두 번째는 배열에 액세스하기 위한 도우미일 뿐입니다.

myfind() {
  IFS=$'\n' __last_find_result=($(find "$@"));
  printf "%s\n" "${__last_find_result[@]}";
}
myget() {
  echo "${__last_find_result[$1]}";
}

사용 사례:

$ myfind . -name "c*"
./a b/c d
./.git/config
./.git/hooks/commit-msg.sample
$ vim "$(myget 0)"
# This opens the "./a b/c d" file.
$ vim "$(myget 2)"
# This opens ".git/hooks/commit-msg.sample"

$(myget index)파일 이름에 공백이나 기타 문제가 되는 문자가 없으면 주위에 따옴표가 필요하지 않습니다.
전체 출력을 find사용자 환경에 푸시합니다. 이는 제한될 수 있습니다. (배열 대신 임시 파일을 사용하면 이 문제가 해결되지만 다른 문제가 있습니다. 특히 여러 셸을 동시에 사용하는 경우가 그렇습니다.)

답변2

나는 이것에 이것을 가지고 있습니다 .screenrc:

bind -c pasteline 1 eval copy 'stuff "-Y"' 'paste .'
bind -c pasteline 2 eval copy 'stuff "2-Y"' 'paste .'
bind -c pasteline 3 eval copy 'stuff "3-Y"' 'paste .'
bind -c pasteline 4 eval copy 'stuff "4-Y"' 'paste .'
bind -c pasteline 5 eval copy 'stuff "5-Y"' 'paste .'
bind -c pasteline 6 eval copy 'stuff "6-Y"' 'paste .'
bind -c pasteline 7 eval copy 'stuff "7-Y"' 'paste .'
bind -c pasteline 8 eval copy 'stuff "8-Y"' 'paste .'
bind -c pasteline 9 eval copy 'stuff "9-Y"' 'paste .'
bindkey ¬ command -c pasteline

기본적으로 화면에서는 , ¬1커서 위에 줄을 붙여넣고, ¬2, 커서 위에 두 번째 줄을 붙여넣는 식으로 진행됩니다. 10행 이상에 대해 더 추가하고 싶을 수도 있지만 행 7 이후에는 screen원하는 행 수를 얻기 위해 행 수를 계산하는 것보다 마우스나 복사 모드를 사용하는 것이 더 좋습니다.

답변3

또 다른 해결책: 선택 사항을 자동으로 묻는 대화형 스크립트를 작성할 수 있습니다. 대화형 스크립트의 코드는 다음과 같습니다.

#!/bin/bash

echo "enter your choice : z for last argument or a number for that file"
read choice

case "$choice" in
z) eval vim \$$#;;
*)eval  vim \$$choice;;
esac

이 스크립트를 "autofind"와 같은 이름으로 저장하고 "find command"를 인수로 사용하여 스크립트를 호출합니다. 다음은 스크립트를 호출하는 코드입니다.

./autofind `your find command`

그러나 스크립트를 사용하기 전에 "find 명령"이 결과를 제공하는지 확인하십시오. 결과가 표시되면 스크립트를 사용하십시오.

답변4

Matz의 대답은 정확히 내가 원했던 것이었습니다. 더 많은 가져오기 옵션을 허용하기 위해 그의 코드를 약간 확장했습니다.

$ f ~/scripts -name '*.sh'
$ vim $(g foo)  # edit all find results matching "foo"
$ vim $(g 1 3 5) # edit find results number 1, 3 and 5
$ vim $(g 3-5) # edit find results 3-5
$ vim $(g 5-) # edit find results 5 to last
$ vim $(g -7) # edit find result 7 from bottom
$ vim $(g 1 4-5 -7 9- foo) # all of the above combined

.

f() {
    IFS=$'\n' __last_find_result=($(find "$@"));
    printf "%s\n" "${__last_find_result[@]}";
}

g() {
    len=${#__last_find_result[@]}
    pad=${#len}
    numbers=""
    if [ "$1" == "-n" ]; then
        numbers=1
        shift
    fi
    if [ -z "$1" ]; then
        if [ -n "$numbers" ]; then
            n=1;
            for e in "${__last_find_result[@]}";do
                printf "%0${pad}d. %s\n" "$n" "$e"
                let n=n+1
            done
        else
            printf "%s\n" "${__last_find_result[@]}"
        fi
    else
        for l in $@;do
            if [[ "$l" =~ ([^0-9-]+) ]];then
                n=1;
                for e in "${__last_find_result[@]}";do
                    if [[ $e =~ $1 ]]; then
                        if [ -n "$numbers" ];then
                            printf "%0${pad}d. %s\n" "$n" "$e"
                        else
                            printf "%s\n" "$e"
                        fi
                    fi
                    let n=n+1
                done
            elif [[ "$l" =~ ^([0-9]+)$ ]];then
                let l=l-1
                echo "${__last_find_result[$l]}";
            elif [[ "$l" =~ ^([0-9]*)(-)?([0-9]*)$ ]]; then
                from=${BASH_REMATCH[1]};
                dash=${BASH_REMATCH[2]};
                to=${BASH_REMATCH[3]};
                if [ -z "$from" ]; then # -n
                    [ $to -gt ${#__last_find_result[@]} ] && to=${#__last_find_result[@]}
                    echo "${__last_find_result[-$to]}";
                else # n-m
                    [ -z "$to" ] && to=${#__last_find_result[@]}
                    [ $to -gt ${#__last_find_result[@]} ] && to=${#__last_find_result[@]}
                    let to=$to-1
                    let from=$from-1
                    n=$(($from+1))
                    for i in `seq $from $to`;do
                        if [ -n "$numbers" ];then
                            printf "%0${pad}d. %s\n" "$n" "${__last_find_result[$i]}"
                        else
                            printf "%s\n" "${__last_find_result[$i]}"
                        fi
                        let n=n+1
                    done
                fi
            fi
        done
    fi
}

관련 정보