명령줄에서 일부 파일을 인수로 받아들이는 프로그램이 있습니다. 역순으로 나열된 디렉토리의 모든 파일을 사용하여 호출하고 싶습니다.
예를 들어:
나는 역순으로 디렉토리에 다음 파일을 가지고 있습니다
$ ls -tr
Introduction.pdf 'Object-Oriented Data Model.pdf'
프로그램을 직접 실행할 수 있고,
myprogram Introduction.pdf 'Object-Oriented Data Model.pdf'
하지만 다른 명령을 통해 파일을 나열하고 싶습니다. 파일 이름 중 하나에 공백이 있어서 작동하지 않습니다.
myprogram $(ls -tr)
ls
출력을 구문 분석하는 것은 좋은 습관이 아니라는 것을 기억합니다 . 제가 도움을 드릴 수 있을지 잘 모르겠습니다 find
.
그래서 내가 무엇을 할 수 있니?
감사해요.
답변1
최신 버전의 GNU 유틸리티가 있는 경우 NULL로 끝나는 데이터를 처리하도록 할 수 있습니다. 이를 통해 데이터 자체의 공백이나 줄바꿈의 영향을 받지 않는 파이프라인을 구축할 수 있습니다.
내 테스트 도구는 다음과 같은 빠른 스크립트입니다 /tmp/args
.
#!/bin/bash
echo "This is args with $# value(s)"
for f in "$@"; do echo "> $f <"; done
명령줄에서 다음과 같이 파일이 마지막으로 수정된 시간을 기준으로 정렬된 파일 이름 범위를 지정할 수 있습니다.
find -type f -printf "%T@ %p\0" | sort -zn | sed -z 's/^[0-9.]* //' | xargs -0 /tmp/args
이 find
명령은 각 파일/경로 이름 앞에 마지막으로 수정된 날짜/시간의 소수 초 표시를 추가합니다. 이는 sort
가장 낮은 것(오래된 것)부터 가장 높은 것(최신)까지 처리됩니다. sed
방금 결과 파일 이름 세트를 정렬하고 에 전달하는 데 사용한 선행 숫자를 제거하십시오 xargs
. 파일 이름에서 선행 숫자를 생략하려면 %p
로 바꾸십시오.%P
./
샘플 데이터
# "c d" contains a space; "e f" contains a newline; "h" has leading whitespace
touch a 'e
f' g ' h ' 'c d' b
결과의 예
This is args with 6 value(s)
> ./a <
> ./e
f <
> ./g <
> ./ h <
> ./c d <
> ./b <
답변2
불다수정 시간별로 파일을 정렬하는 것은 아직 쉽지 않습니다., 따라서 이것은 zsh를 기반으로 한 필수 답변입니다. 해당 기능을 사용하기 위해 로그인 셸로 zsh로 전환할 필요는 없습니다.
여기서는 하나 또는 두 개의 인수를 사용하는 래퍼 함수를 설정했습니다. 첫 번째 인수는 실행할 프로그램(예: myprogram
)이고 두 번째 선택적 인수는 프로그램에 전달할 파일이 포함된 디렉터리입니다. 두 번째 매개변수를 지정하지 않으면 기본값은 현재 디렉터리입니다.
zeio() {
# Zsh-based Execute with files In Order
[ -d "${2:-.}" ] || return
zsh -c "$1 \"${2:-.}\"/*(.om)"
}
물론 이름은 원하는 대로 지정할 수 있습니다. 두 번째 인수(다시 기본값은 현재 디렉터리)에 대한 빠른 온전성 검사 후 .
, 프로그램과 일부 초기 인수(인수 #1) 및 디렉터리(인수 #1)를 포함하는 단일 큰따옴표 문자열을 사용하여 zsh를 호출합니다. ) — 기본값은 .
— 와일드카드/전역 확장을 두 개로 사용합니다."글로벌 예선"다음 괄호 안에:
.
-- 일반 파일이어야 합니다(디렉토리나 심볼릭 링크 등이 아님).om
o
--결과 목록을 수정 시간순으로 최신순으로 정렬 (정렬)합니다.
om
여기서 실제 작업을 모두 수행하는 것은 바로 이 glob 한정자입니다 .
myprog
다음은 수신하는 인수를 순서대로 보여주는 데 사용되는 몇 가지 예제 실행입니다 .
#!/bin/sh
for arg do
printf 'Arg: ->%s<-\n' "$arg"
done
go.sh
함수를 저장하는 파일 입니다 . 나머지 디렉토리 구조는 다음과 같습니다.
$ tree .
.
├── dir1
│ ├── 203142
│ ├── 203143
│ └── 203144
├── dir3
│ ├── first\012filename
│ ├── this is 3rd
│ └── this is second
├── dir two
│ ├── 203225
│ ├── 203226
│ └── 203227
├── go.sh
└── myprog
...각 하위 디렉터리에 나열된 순서대로 세 개의 파일 세트를 만들었습니다. 함수가 실행될 때 동일한 순서로 표시하고 싶습니다. dir3 아래의 첫 번째 파일 이름에는 tree
with 로 표시되는 개행 문자가 있습니다 \012
. 결과 :
현재 디렉터리를 기본값으로 설정하는 동작을 보여줍니다.
$ zeio ./myprog
Arg: ->./myprog<-
Arg: ->./go.sh<-
일반 파일 이름 데모
$ zeio ./myprog dir1
Arg: ->dir1/203142<-
Arg: ->dir1/203143<-
Arg: ->dir1/203144<-
디렉토리에 공백이 있습니다
$ zeio ./myprog "dir two"
Arg: ->dir two/203225<-
Arg: ->dir two/203226<-
Arg: ->dir two/203227<-
파일 이름에 공백이 있습니다
$ zeio ./myprog dir3
Arg: ->dir3/first
filename<-
Arg: ->dir3/this is second<-
Arg: ->dir3/this is 3rd<-
답변3
(IFS=$'\n'; set -f; your_program $(ls -tr))
파일 이름에 개행 문자가 포함되어 있지 않다고 가정합니다.
예:
% touch 'a b'
% touch 'c d'
% touch '*'
% (IFS=$'\n'; set -f; printf '%s\n' $(ls -tr))
e f
a b
c d
*
문자열을 지원하지 않는 $'...'
표준 셸의 변형 :
(IFS='
' ; set -f; your_program $(ls -tr))
파일 이름에 개행 문자가 포함되어 있어도 작동하는 간단한 Python 래퍼입니다. 그냥 사용하세요 this_wrapper your_program *
.
#! /usr/bin/python
import os
import sys
sys.argv[2:] = sorted(sys.argv[2:], key=os.path.getmtime)
os.execvp(sys.argv[1], sys.argv[1:])