Script de bash: verifique se um arquivo é um arquivo de texto [closed]

3

Estou escrevendo um script bash baseado em menu, uma das opções do menu é enviar um email com um anexo de arquivo de texto. Estou com problemas para verificar se meu arquivo é um arquivo de texto. Aqui está o que eu tenho:

fileExists=10
until [ $fileExists -eq 9 ]
do
  echo "Please enter the name of the file you want to attach: "
  read attachment
  isFile=$(file $attachment | cut -d\ -f2)
  if [[ $isFile = "ASCII" ]]
    then
      fileExists=0
    else
      echo "$attachment is not a text file, please use a different file"
  fi
done

Continuo recebendo o erro de corte: o delimitador deve ser um único caractere.

    
por Powea 11.06.2015 / 11:33

5 respostas

2

O problema ocorre em cut -d\ -f2 . Mude para cut -d\ -f2 .

Para cut , os argumentos são assim:

# bash: args(){ for i; do printf '%q \\n' "$i"; done; }
# args cut -d\ -f2
cut \
-d\ -f2 \

E aqui está o problema. \ escapou do espaço para um literal de espaço em vez de um delimitador entre argumentos em seu shell, e você não adicionou um espaço extra para que toda a parte -d\ -f2 apareça como um argumento. Você deve adicionar um espaço extra, então -d\ e -f2 aparecem como dois argumentos.

Para evitar confusão, muitas pessoas usam citações como -d' ' .

P.S .: Em vez de usar o arquivo e fazer tudo como ASCII, prefiro usar

if file "$attachment2" | grep -q text$; then
    # is text
else
    # file doesn't think it's text
fi
    
por 12.06.2015 / 12:37
8
  1. Do fato de que diz file $attachment em vez de file "$attachment" , Eu acho que seu script não pode manipular nomes de arquivos que contenham espaços. Mas, esteja ciente de que nomes de arquivos podem conter espaços, e scripts bem escritos podem lidar com eles. Observe, então:

    $ file "foo bar"
    foo bar:  ASCII text
    
    $ file "foo bar" | cut -d' ' -f2
    bar:
    

    Uma abordagem popular e altamente recomendada é anular em branco os nomes dos arquivos:

    $ file -0 "foo bar" | cut -d $'
    isFile=$(file -0 "$attachment" | cut -d $'
    $ file "foo bar"
    foo bar:  ASCII text
    
    $ file "foo bar" | cut -d' ' -f2
    bar:
    
    ' -f2) case "$isFile" in (*text*) echo "$attachment is a text file" ;; (*) echo "$attachment is not a text file, please use a different file" ;; esac
    ' -f2 : ASCII text
  2. O comando file faz suposições sobre que tipo de arquivo é um arquivo. As suposições, naturalmente, estão erradas em algum momento. Por exemplo, file às vezes vai olhar para um arquivo de texto comum e acho que é um script de shell, um programa em C ou outra coisa. Então você não quer verificar se a saída de file é ASCII text , Você quer ver se diz que o arquivo é um arquivo de texto. Se você olhar para a página man do file , você vai ver que mais ou menos promessas para incluir a palavra text em sua saída se o arquivo for um arquivo de texto, mas isso pode estar em um contexto como shell commands text . Então, pode ser melhor verificar se a saída de file contém a palavra text :

    $ file -0 "foo bar" | cut -d $'
    isFile=$(file -0 "$attachment" | cut -d $'%pre%' -f2)
    case "$isFile" in
       (*text*)
          echo "$attachment is a text file"
          ;;
       (*)
          echo "$attachment is not a text file, please use a different file"
          ;;
    esac
    
    ' -f2 : ASCII text
por 11.06.2015 / 13:28
4
case $(file -b --mime-type - < "$attachment") in
  (text/*)
     printf '%s\n' "$attachment is probably text according to file"
     case $(file -b --mime-encoding - < "$attachment") in
       (us-ascii) echo "and probably in ASCII encoding"
     esac
esac
    
por 11.06.2015 / 14:39
3

Eu contornaria o escape e faria:

... | cut -d' ' -f2 

Dessa forma, fica claro que você precisa de um espaço entre o caractere delimitador (especificado pela seqüência de três letras ' ' ) e a opção a seguir. Com -d\ -f2 é fácil errar, você deveria ter feito -d\ -f2 .

    
por 11.06.2015 / 11:38
2

Outra opção é não usar cut e corresponder a uma expressão regular em relação à saída completa de file :

#...
isFile=$(file $attachment)
if [[ "$var" =~ ^[^:]*:\ ASCII ]]
#...
    
por 11.06.2015 / 13:04