`locate` 결과 중 하나를 선택하고 지정된 응용 프로그램으로 열 수 있게 하려면 어떻게 해야 합니까?

`locate` 결과 중 하나를 선택하고 지정된 응용 프로그램으로 열 수 있게 하려면 어떻게 해야 합니까?

findme다음과 같이 코딩된 bash 스크립트가 있습니다 .

#!/bin/bash
locate -Abi '*\.'$1 $2 | grep --color=always -ni $2 | less -R

파일 이름에 패턴(다음 제공된 인수)이 있고 지정된 파일 확장자(스크립트에 제공된 첫 번째 인수)가 있는 모든 파일을 검색합니다.
다음을 실행하면 :

user@machine$ findme pdf classifi

pdf파일 이름에 포함된 모든 파일을 검색합니다 classifi. 그래서 다음과 같은 결과를 얻을 수 있습니다.

1:/홈/사용자/Dropbox/SharedWithFriends/수학/분류cations2000.pdf
2:/home/user/Dropbox/SharedWithFriends/math/분류양이온2010.pdf

질문은 ~이야: "결과를 표시한 후 다음 작업을 자동화하기 위해 숫자와 뷰어를 요청하는 bash 스크립트 코드를 제공해 주실 수 있나요?"

예를 들어 다음과 같이 입력하고 싶습니다.

> 2 evince

스크립트는 검색 결과의 두 번째 항목 evince에서 실행됩니다.2, 이전 검색 결과에 입력한 내용이 다음과 같은 경우 실행됩니다.

evince /home/user/Dropbox/SharedWithFriends/math/classifications2010.pdf

답변1

findme다음은 결과를 가져오는 함수 의 변형입니다 . 그러나 결과 grep에 번호를 매기거나 less페이지를 지정하는 대신 내부 배열에서 결과를 나열한 다음 항목 및 프로그램 선택을 묻는 메시지를 표시합니다.

#!/usr/bin/env bash

readarray -O 1 -t results < <(locate -Abi '*\.'"$1" "$2" | grep --color=always -i "$2")

for((i=1; i <= ${#results[*]}; i++))
do
  printf "%d: %s\n" $i "${results[i]}"
done
read -p "> " item program
$program "${results[item]}"

파일 이름이나 grep 매개변수의 공백을 더 잘 처리하기 위해 원본 스크립트에 인용문을 추가했습니다. readarray결과가 0이 아닌 인덱스 1에서 시작하여 grep의 번호 매기기에 해당하도록 호출을 조정했습니다 .

답변2

스크립트 에는 findme몇 가지 문제가 있습니다.

  • 변수 대체에 큰따옴표가 누락되었습니다.
  • 의 출력은 grep --color=always명령 대체에 사용할 수 없는 결과를 생성합니다. 통과하려면 필요 less하지만 스크립트에서 재사용하지 마십시오.
  • grep 및 찾기는 다른 패턴 구문을 사용하므로 grep두 번째 인수에 색상을 지정하는 데 사용하는 것이 항상 작동하는 것은 아닙니다. -r에 전달하면 locate정규식을 사용하게 되지만 Emacs 구문은 grep이 지원하는 구문과 약간 다릅니다.

bash에서는 다음을 사용할 수 있습니다.mapfile일부 라인을 배열에 안정적으로 채우는 것입니다. 그것을 결합하십시오프로세스 대체명령의 출력을 사용합니다. 그런 다음 해당 배열을 인쇄하고 사용자 입력을 읽습니다.

findrun () {
  mapfile search_hits <(locate -Abir ".*\.$1" "$2")
  print '%s\n' "${search_hits[@]}" | grep --color=always -ine "$2"
  if read -a cmd; then
    set -- "${cmd[@]}"
    set -- "$@" "${search_hits[$1]}"
    shift
    "$@"
  fi
}

대체 인터페이스는 위치 매개변수를 설정하는 것입니다. 함수에서 위치 매개변수를 변경할 수 없기 때문에 약간 까다롭습니다.Bash에서 그것을 수행하는 우회 방법별칭을 사용하고 스크립트를 소싱합니다. 인용에 주의하세요.

alias findrun='. <(echo findrun_prepare \"\$@\"; echo set -- "\"\${search_hits[@]}\"")'
findrun_prepare () {
  mapfile search_hits <(locate -Abir ".*\.$1" "$2")
  print '%s\n' "${search_hits[@]}" | grep --color=always -ine "$2" >&2
}

용법:

findrun pdf classifi
evince "$2"

답변3

Jeff Schaller가 제공한 솔루션을 기반으로 합니다. 해결책을 찾았습니다. 귀하의 의견을 받아 더 나은 결과를 얻으면 기쁠 것입니다.

#!/bin/bash

readarray -O 1 -t results < <(locate -Abi '*\.'"$1" "$2")

for((i=1; i <= ${#results[*]}; i++))
do
  printf "%d: %s" $i "${results[i]}" | grep --color=always -i "$2"
done

read -p "> " item program

$program "${results[item]}"

이것은 간단한(주제의 복잡성에 따라) 답변처럼 보입니다.

그러나 결과가 특정 숫자 이상이면 충분하지 않습니다! 이 경우 우리는 다음과 같은 것이 필요합니다 more.less

관련 정보