シェルスクリプトでsftpを使用してリモートの場所にあるファイルの数を計算する

シェルスクリプトでsftpを使用してリモートの場所にあるファイルの数を計算する

リモートディレクトリで特定の種類のファイルを確認するために、次のコマンドを使用中にエラーが発生しました。要件は、特定のファイルの数を取得することです。

file_exists=$(sftp $FTP_UNAME@$FTP_HOST ls *$FILE_ID*.txt | wc -l)

これはよく書かないのですか?助けてください...

Below is the Usage Tip - 
usage: sftp [-1246aCfpqrv] [-B buffer_size] [-b batchfile] [-c cipher]
          [-D sftp_server_path] [-F ssh_config] [-i identity_file] [-l limit]
          [-o ssh_option] [-P port] [-R num_requests] [-S program]
          [-s subsystem | sftp_server] host
       sftp [user@]host[:file ...]
       sftp [user@]host[:dir[/]]
       sftp -b batchfile [user@]host

答え1

sftpスクリプトで安定して使用することは困難です。代わりに、一部のプログラミング言語のSFTPモジュールを使用できます。 Perlを例に挙げましょうNet::SFTP::Foreign

perl -MNet::SFTP::Foreign -le '
  ($host, $dir, $id) = @ARGV;
  $s = Net::SFTP::Foreign->new($host, autodie => 1, fs_encoding => latin1);
  print scalar @{
    $s->ls($dir, names_only => 1, wanted => qr/\Q$id\E.*\.txt\z/s)
  }' -- "$FTP_UNAME@$FTP_HOST" . "$FILE_ID"

名前にログインディレクトリが含まれ、終了するファイルの数を報告します$FILE_ID。ファイルに含まれる内容(問題を引き起こす可能性のある空白など)とファイル名に含まれるすべての内容(問題になる可能性がある改行文字も含む)に関係なくです。.txt$FILE_ID;sftpwc -l

latin1エンコーディングはUTF-8デコードを試みず、ファイルパスでランダムなバイト値を使用します。)

シェル配列のファイルのリストを取得するには、次のようにしますzsh

files=( ${(0)"$(
  perl -MNet::SFTP::Foreign -l0 -e '
  ($host, $dir, $id) = @ARGV;
  $s = Net::SFTP::Foreign->new($host, autodie => 1, fs_encoding => latin1);
  print for @{
    $s->ls($dir, names_only => 1, wanted => qr/\Q$id\E.*\.txt\z/s)
  }' -- "$FTP_UNAME@$FTP_HOST" . "$FILE_ID")"}
)

バッシュ4.4+の場合:

readarray -td '' files < <(
  perl -MNet::SFTP::Foreign -l0 -e '
  ($host, $dir, $id) = @ARGV;
  $s = Net::SFTP::Foreign->new($host, autodie => 1, fs_encoding => latin1);
  print for @{
    $s->ls($dir, names_only => 1, wanted => qr/\Q$id\E.*\.txt\z/s)
  }' -- "$FTP_UNAME@$FTP_HOST" . "$FILE_ID")

終了状態は失われますがperl

答え2

で述べたように手動SFTP-b(1) (バッチモード) 引数が与えられない場合、対話モードに入ります。コマンドをパイプで接続します。SFTP、指定された特殊ファイル名-、例:

printf "ls\n" | sftp -b- server.example.com

コマンドに引用符がないワイルドカード文字が含まれています。この文字はパス名拡張中にシェルで解釈され、次に適用されます。ローカル現在のディレクトリ(望ましくない可能性があります)したがって、パラメータを引用符で囲む必要があります。また、パラメータを渡す必要があります-1SFTPls出力される行数を計算したい場合はコマンドです。

最後に、コマンドの出力行にはlsインタラクティブなプロンプトとコマンド自体が含まれているため、数を1つ減らす必要があります。これを達成する方法には、次の構造で算術拡張を使用するなど、さまざまな方法があります。

printf "%d\n" $(( $( ... ) - 1))

付録:@Stéphane Chazelasが述べたように、OPがファイルを計算する方法のため、このソリューションには改行文字を含むファイル名に問題があります(もちろんそうではありませんが、理論的には可能です)。トイレ持っている完全な質問と回答出力を解析しない理由エルエス(ユーティリティ)、そして何をすべきか結論はStéphaneのものと似ています。また、トイレディレクトリとファイルを区別しないでください。重要です。ワイヤー、ディレクトリとファイルが含まれています。同様に、パターンはパラメータとして渡されます。SFTPコマンドにスペースが含まれている場合はls効果がありません。参照内で参照できますが、複雑さが追加されます。

printf "ls -1 *\"$FILE_ID\"*.txt\n" | ...

私の答えの後ろに隠されたアイデアは、「これは間違って書かれていますか?」という質問に答えるよりも教育的です。すべての状況で動作するソリューションを提供するよりも。

関連情報