Como usar um arquivo de entrada de nomes de arquivos não exatos para uma operação?

3

Eu tenho um arquivo de nomes de arquivos para arquivos em um determinado diretório. No entanto, alguns dos nomes dos arquivos podem:

  1. Ter espaços no nome do arquivo original substituídos por sublinhados (portanto, directory/file with spaces se torna file_with_spaces no arquivo de entrada)
  2. Pode não corresponder a um arquivo no diretório

Se eu não tivesse essas duas condições, usaria cat inputfile | awk 'commands' para processar os comandos desejados no arquivo. No entanto, eu gostaria de alguma forma de pegar o nome do arquivo não encontrado erros e também:

  1. Tente com diferentes combinações de sublinhados sendo substituídos por espaços até encontrar um arquivo correspondente
  2. Forneça uma lista de arquivos que não tiveram correspondências, mesmo depois de substituir espaços por sublinhados.

Existe uma boa maneira de fazer isso? Eu suspeito que algum tipo de script será necessário (ao invés de um comando de uma linha), mas eu ainda não estou familiarizado com o shell script o suficiente para pensar na solução.

    
por cjm 14.01.2017 / 22:37

3 respostas

0

A abordagem que eu usaria é pegar a saída de ls, configurar um array mapeando o nome convertido de volta para o nome original e, em seguida, processar cada linha do arquivo de entrada. Se a entrada estiver na matriz, emita o valor da matriz, caso contrário, inclua a linha de entrada no arquivo missing . Então, algo como colocar isso em um arquivo, altere para o directory e execute-o com inputfile como um parâmetro

#!/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"
        }
    }
    
por 15.01.2017 / 05:52
0

Transforme os nomes dos arquivos inseridos em padrões que correspondam ao arquivo original.

#!/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
    
por 16.01.2017 / 01:13
0

Com zsh , você pode usar seu recurso de correspondência aproximada:

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
}

E ligue para:

approx-cat 3 'directory/file with spaces'

Para permitir até 3 erros no nome do arquivo.

Exemplo:

$ 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
    
por 16.01.2017 / 15:51