web-dev-qa-db-ja.com

Bashスクリプト:ファイルがテキストファイルかどうかを確認する

私はメニューベースのbashスクリプトを書いています。メニューオプションの1つは、テキストファイルが添付された電子メールを送信することです。ファイルがテキストファイルかどうかを確認できません。これが私が持っているものです:

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

エラーが発生し続けます。区切り文字は1文字でなければなりません。

3
Powea

問題はcut -d\ -f2で発生します。 cut -d\ -f2に変更します。

cutの場合、引数は次のようになります。

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

そしてここに問題があります。 \は、シェルの引数間の区切り文字の代わりにスペースリテラルにスペースをエスケープし、余分なスペースを追加しなかったため、-d\ -f2部分全体が1つの引数として表示されます。 -d\-f2が2つの引数として表示されるように、スペースを1つ追加する必要があります。

混乱を避けるために、多くの人々は代わりに-d' 'のような引用符を使用しています。

PS:ファイルを使用してすべてをASCIIにする代わりに、私はむしろ

if file "$attachment2" | grep -q text$; then
    # is text
else
    # file doesn't think it's text
fi
2
Arthur2e5
  1. file $attachmentではなくfile "$attachment"と表示されていることから、スクリプトではスペースを含むファイル名を処理できないと思います。ただし、ファイル名にはスペースを含めることができ、適切に記述されたスクリプトはそれらを処理できることに注意してください。注意してください:

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

    ファイル名をnullで終了することは、一般的で強く推奨されるアプローチの1つです。

    $ file -0 "foo bar" | cut -d $'\0' -f2
    :  ASCII text
    
  2. fileコマンドは、ファイルがどのタイプのファイルであるかについて、知識に基づいた推測を行います。当然、推測は時々間違っています。たとえば、fileは、通常のテキストファイルを見て、それがシェルスクリプト、Cプログラム、またはその他のものであると推測する場合があります。したがって、fileisASCII textからの出力がファイルであるかどうかを確認する必要はありませんsaysテキストファイル。 fileのmanページを見ると、ファイルがテキストファイルの場合、出力にWord textを含めることが多少なりとも約束されていることがわかりますが、これはShell commands textのようなコンテキストにあるしたがって、fileからの出力にWord textが含まれているかどうかを確認することをお勧めします。

    isFile=$(file -0 "$attachment" | cut -d $'\0' -f2)
    case "$isFile" in
       (*text*)
          echo "$attachment is a text file"
          ;;
       (*)
          echo "$attachment is not a text file, please use a different file"
          ;;
    esac
    
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
4

私は脱出を回避して行います:

... | cut -d' ' -f2 

このように、区切り文字(3文字のシーケンス' 'で指定)と次のオプションの間にスペースが必要であることは明らかです。 -d\ -f2を使用すると、-d\ -f2を実行する必要があるはずです。

3
Anthon

別のオプションは、cutを使用せず、fileの完全な出力に対して正規表現を照合することです。

#...
isFile=$(file $attachment)
if [[ "$var" =~ ^[^:]*:\ ASCII ]]
#...
2
kos