find
다음과 같은 최소 작업 예제를 사용하여 함수 안에 넣고 함수에 전달된 인수를 캡처해 보았습니다 .
기능 DO { ls $(find .-type f -name "$@" -exec grep -IHl "TODO" {} \;) }
그러나 실행하면 DO *.tex
"find: path must beforeexpression:"이 표시됩니다. 하지만 내가 직접 이 작업을 수행하면 다음과 같습니다.
ls $(find .-type f -name "*.tex" -exec grep -IHl "TODO" {} \;)
그런 다음 "TODO"가 포함된 모든 TeX 파일을 얻습니다.
DO
함수에서 많은 것을 시도했습니다. 예를 들어 ,,, \"$@\"
따옴표 '$@'
를 변경했지만 동작은 여전히 동일합니다.
그렇다면 함수 내에서 작업을 강제로 찾으려면 어떻게 해야 할까요?
답변1
코드에 몇 가지 문제가 있습니다.
패턴이 현재 디렉터리의 파일 이름과 일치하는 경우
*.tex
이 함수가 호출될 때 패턴이 확장됩니다. 이 함수를 호출할 때DO
패턴을'*.tex'
,"*.tex"
또는 으로 참조해야 합니다.\*.tex
불필요한
ls
. 이미 두 가지가 모두 있으며find
발견grep
된 파일의 경로 이름을 보고할 수 있습니다.-name "$@"
"$@"
단일 항목을 포함하는 경우에만 올바르게 작동합니다. 이용하시면 더 좋을 것 같습니다-name "$1"
. 여러 모드를 허용하는 솔루션은 아래를 참조하세요.
이 함수는 다음과 같이 작성할 수 있습니다.
DO () {
# Allow for multiple patterns to be passed,
# construct the appropriate find expression from all passed patterns
for pattern do
set -- "$@" '-o' '-name' "$pattern"
shift
done
# There's now a -o too many at the start of "$@", remove it
shift
find . -type f '(' "$@" ')' -exec grep -qF 'TODO' {} ';' -print
}
이 함수를 이렇게 호출하세요
DO '*.tex' '*.txt' '*.c'
실행하게 해줄게
find . -type f '(' -name '*.tex' -o -name '*.txt' -o -name '*.c' ')' -exec grep -qF TODO {} ';' -print
파일에 문자열이 포함되어 있으면 해당 파일 이름 접미사가 있는 파일에 대한 경로 이름 목록이 생성됩니다 TODO
.
찾은 경로 이름을 인쇄 grep
하는 대신 사용하려면 비트를 로 변경하십시오 . 이는 특히 특정 표현식과 일치하는 파일 이름이 많은 경우 더욱 효율적입니다. 두 경우 모두 를 사용할 필요가 전혀 없습니다 .find
-exec ... -print
-exec grep -lF 'TODO' {} +
ls
사용자가 사용할 수 있도록
DO tex txt c
귀하의 기능은 다음과 같이 변경될 수 있습니다.
DO () {
# Allow for multiple patterns to be passed,
# construct the appropriate find expression from all passed patterns
for suffix do
set -- "$@" '-o' '-name' "*.$suffix" # only this line (and the previous) changed
shift
done
# There's now a -o too many at the start of "$@", remove it
shift
find . -type f '(' "$@" ')' -exec grep -qF 'TODO' {} ';' -print
}
답변2
함수에 인수를 인용해야 합니다. 그렇지 않으면 셸이 인수를 확장하고 함수는 와일드카드 마스크 대신 파일 목록을 가져옵니다.
DO "*.tex"
그러면 매개변수가 하나만 있으므로 "$1"
대신 사용할 수 있습니다 ."$@"