쉘 스크립트에서 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

명령에 따옴표가 없는 와일드카드 문자가 포함되어 있습니다. 이 문자는 경로 이름 확장 중에 셸에서 해석되어 다음에 적용됩니다.로컬 현재 디렉터리(바람직하지 않을 수 있음) 따라서 매개변수를 따옴표로 묶어야 합니다. 또한 매개변수를 전달해야 합니다 -1.SFTPls출력되는 라인 수를 계산하려는 경우 명령입니다 .

마지막으로 명령의 출력 줄에는 ls대화형 프롬프트와 명령 자체가 포함되므로 개수를 1씩 줄여야 합니다. 이를 달성하는 방법에는 다음과 같은 구조에서 산술 확장을 사용하는 등 다양한 방법이 있습니다.

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

부록:@Stéphane Chazelas가 말했듯이 OP가 파일을 계산하는 방식으로 인해 이 솔루션에는 개행 문자가 포함된 파일 이름에 문제가 있습니다(물론 그럴 가능성은 거의 없지만 이론적으로는 가능합니다).화장실;가지다완전한 질문과 답변출력을 구문 분석하지 않는 이유엘에스(유틸리티), 그리고 무엇을 해야할지 결론은 Stéphane의 것과 유사합니다. 또한,화장실디렉토리와 파일을 구별하지 마십시오. 중요합니다.철사, 디렉터리와 파일이 포함되어 있습니다. 마찬가지로 패턴은 매개변수로 전달됩니다.SFTP명령에 공백이 포함되어 있으면 ls아무 효과가 없습니다 . 참조 내에서 참조할 수 있지만 복잡성이 추가됩니다.

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

내 대답 뒤에 숨겨진 아이디어는 "이것이 잘못 쓰여졌습니까?"라는 질문에 대답하는 것보다 더 교육적입니다. 모든 상황에서 작동하는 솔루션을 제공하는 것보다.

관련 정보