파일 이름이 정확하지 않은 입력 파일을 처리하는 방법은 무엇입니까?

파일 이름이 정확하지 않은 입력 파일을 처리하는 방법은 무엇입니까?

특정 디렉토리에 파일 이름이 있는 파일이 있습니다. 그러나 일부 파일 이름은 다음과 같습니다.

  1. 원래 파일 이름의 공백을 밑줄로 바꿉니다(따라서 directory/file with spaces입력 파일에서도 공백이 됩니다).file_with_spaces
  2. 실제로 디렉터리의 파일과 일치하지 않을 수 있습니다.

이 두 가지 조건이 없다면 cat inputfile | awk 'commands'파일에 원하는 명령을 적용하는 데 사용할 것입니다. 그러나 파일 이름을 찾을 수 없음 오류를 잡을 수 있는 방법이 필요합니다.

  1. 일치하는 파일을 찾을 때까지 밑줄을 공백으로 바꾸는 다양한 조합을 시도해 보세요.
  2. 밑줄을 공백으로 바꾼 후에도 일치하지 않는 파일 목록을 제공합니다.

이를 수행할 수 있는 좋은 방법이 있습니까? 한 줄 명령이 아닌 특정 유형의 스크립트가 필요한 것 같지만 솔루션을 생각할 만큼 쉘 스크립트에 익숙하지 않습니다.

답변1

내가 사용한 접근 방식은 ls의 출력을 가져와 변환된 이름을 다시 원래 이름으로 매핑하는 배열을 설정한 다음 입력 파일의 각 줄을 처리하는 것이었습니다. 입력이 배열에 있으면 배열의 값을 출력하고, 그렇지 않으면 입력 줄을 파일에 추가합니다 missing. 따라서 파일에 넣는 것과 같이 변경하여 인수로 directory실행하십시오.inputfile

#!/usr/bin/awk
# set up an array t of translations
BEGIN {
    while (("ls" | getline )>0) {
        k=$0
        gsub(/ /,"_")
        if ($0 in t) {
            print "$0 matches more than one file" > /dev/stderr
            exit(2)
        }
        t[$0]=k
    }
    close("ls")
}
    { if ($0 in t) {
            print t[$0]
        } else {
            print $0 > "../missing"
        }
    }

답변2

수정된 파일 이름을 원본 파일과 일치하는 패턴으로 변환합니다.

#!/bin/bash
shopt -s nullglob extglob
IFS=$'\n'
while read -r filename; do
  pattern=${filename//\\/\\\\}
  pattern=${pattern//\[/\\\[}
  pattern=${pattern//\(/\\\(}
  pattern=${pattern//\*/\\\*}
  pattern=${pattern//\?/\\\?}
  pattern=${pattern//_/'[ _]'}
  matches=($pattern@())
  case ${#matches[@]} in
    0) echo "No match for $filename";;
    1) echo "$filename found as ${matches[0]}";;
    *) echo "$filename matches ${#matches[@]} files";;
  esac
done <inputfile

답변3

을 사용하면 zsh대략적인 일치 기능을 사용할 수 있습니다.

approx-cat() {
  emulate -L zsh
  setopt extendedglob nullglob
  local err files
  for ((err = 0; err <= $1; err++)); do
    files=((#a$err)$2)
    case $#files in
      (1) cat -- $files; return;;
      (0) ;;
      (*) echo >&2 "$#files found at error count $err:"
          printf >&2 '  "%s"\n' $files
          return 1;;
    esac
  done
  return 1
}

다음과 같이 호출됩니다.

approx-cat 3 'directory/file with spaces'

최대 3개 허용실수파일 이름에.

예:

$ approx-cat 3 /ebc/passwds
2 found at error count 2:
  "/etc/passwd"
  "/etc/passwd-"
$ approx-cat 3 /ebc/Issue
Debian GNU/Linux stretch/sid \n \l

관련 정보