이 코드 줄이 있습니다
scp -r ${server}:${server_dir}/$(ssh ${server} "ls -t ${server_dir} | head -5") logs/ios
실행 시 5개 파일 중 최신 파일만 scp되며 출력은 다음과 같습니다.
iosTestOutput_20180831-175508-PDT.tgz 100% 199KB 21.7MB/s 00:00
cp: iosTestOutput_20180831-155546-PDT.tgz: No such file or directory
cp: iosTestOutput_20180831-142509-PDT.tgz: No such file or directory
cp: iosTestOutput_20180831-124259-PDT.tgz: No such file or directory
cp: iosTestOutput_20180831-115001-PDT.tgz: No such file or directory
그러나 실제로 대상 디렉토리에 ssh를 연결하고 이러한 파일이 존재하는 것을 관찰했기 때문에 내가 뭘 잘못하고 있는지 잘 모르겠습니다.
답변1
첫 번째 파일에만 scp에 필요한 절대 경로가 있습니다.
${server}:${server_dir}/$(ssh ${server} "ls -t ${server_dir} | head -5")
으로 평가될 것이다
${server}:${server_dir}/iosTestOutput_20180831-175508-PDT.tgz
iosTestOutput_20180831-155546-PDT.tgz
iosTestOutput_20180831-142509-PDT.tgz
...
명확성을 위해 공백 대신 개행 문자를 사용했습니다.
기본적으로 5개 파일 출력 각각에 대한 전체 경로의 내용을 사용하여 생성된 목록을 반복해야 합니다.https://unix.stackexchange.com/a/240424/162359좋은 시작이 될 수도 있습니다.
(테스트되지 않음, 대략적인 스케치임) 다음과 같습니다.
for bkp in $(ssh ${server} "find ${absolute_path_remote_dir} -type f -exec stat -c '%X %n' {} \; | sort -nr | awk 'NR==1,NR==5 {print $2}'")
do
scp -r ${bkp} logs/ios
done
rsync에는 원하는 것을 더욱 우아하게 달성하는 데 도움이 되는 옵션이 있을 수도 있습니다.
답변2
실행할 때:
scp -r ${server}:${server_dir}/$(ssh ${server} "ls -t ${server_dir} | head -5")
...일어나는 첫 번째 (중요한) 일은 로컬 쉘이 여기에서 명령 대체를 해석하기 시작한다는 것입니다.
$(ssh ${server} "ls -t ${server_dir} | head -5")
위의 명령 대체는 대부분 생각대로 작동합니다. 파일 이름에 공백이나 개행(또는 탭)이 있으면 바로 중단됩니다. 예를 들어 다음과 같은 5개의 최신 파일이 있을 수 있습니다.
temp file
a
b
c
d
귀하에게는 다음이 제공 됩니다 ssh ... ls -t | head -5
:
a
b
c
d
temp file
...그러나 명령 대체는 출력에서 줄 바꿈을 제거하고 다음 문자열을 반환합니다.
a b c d temp file
...이제 실제 원본 파일 이름과 구별할 수 없습니다.
이와 같은 파일 이름은 결코 접하지 못할 수도 있지만, 그 반대의 경우보다 안전하고 물리지 않는 것이 더 안전합니다.
따라서 파일 이름을 로컬 시스템으로 안전하게 검색한 다음 구체적으로 검색하는 것이 좋습니다.
server=server-name-here ## replace with your values
server_dir=/tmp ## replace with your values
files=($(ssh "$server" "zsh -c 'print -N -- ${server_dir}/*(om.[1,5])'" 2>/dev/null ) )
for f in ${files[1,5]}
do
scp "${server}:${f}" logs/ios
done
가장 어려운 부분은 가장 최근에 수정된 5개 파일의 원격 목록을 검색하는 것입니다. 여기서는 ssh를 통해 서버에 연결하고 zsh를 호출하여 광범위한 글로빙 메커니즘을 사용하여 반환합니다.
- ${server_dir}의 파일
o
m
산화 시간별 로 정렬.
일반 파일( ) 입니다 .- 그리고 처음 5개는 다음과 같습니다.
[1,5]
여기서는 zsh 내장 명령을 사용하여 print
null로 구분되고 null로 끝나는 결과 파일 목록을 반환합니다. null을 포함하는 이 문자열은 ssh를 통해 zsh로 다시 전달되며, 이는 문자열을 null로 분할하고 내용을 배열에 할당합니다 files
.
그런 다음 처음 5개 요소(6번째 요소는 null이므로)만 가져오도록 주의하면서 배열을 반복하고 scp
각 파일을 차례로 호출합니다.
원한다면 원격 파일 이름 문자열( ${server}:${file1} ${server}:${file2} ...
)을 신중하게 작성하고 scp
한 번만 호출할 수 있습니다. 한 가지 가능성은 다음과 같습니다.
scp ${server}:${(qq)^files[1,5]} logs/ios
...이것은 zsh가 배열의 처음 5개 요소에 문자열(실제 서버 이름으로 대체된 ${server}, 그 뒤에 콜론이 옴)을 추가하도록 지시하기 때문입니다. 배열의 모든 파일 이름이 참조됩니다.
답변3
hhoke1이 말했듯이 절대 경로가 누락되었습니다.
ls -t | head -5 | xargs readlink -f
이것은 scp에 대한 절대 경로를 제공해야 하지만 readlink
파이프에서 입력을 읽을 수 없는 것 같아서 xargs
.