명령을 통해 파일을 시간 역순으로 나열하고 이를 다른 명령에 인수로 전달하는 방법은 무엇입니까?

명령을 통해 파일을 시간 역순으로 나열하고 이를 다른 명령에 인수로 전달하는 방법은 무엇입니까?

명령줄에서 일부 파일을 인수로 받아들이는 프로그램이 있습니다. 역순으로 나열된 디렉토리의 모든 파일을 사용하여 호출하고 싶습니다.

예를 들어:

나는 역순으로 디렉토리에 다음 파일을 가지고 있습니다

$ 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를 호출합니다. ) — 기본값은 .— 와일드카드/전역 확장을 두 개로 사용합니다."글로벌 예선"다음 괄호 안에:

  1. .-- 일반 파일이어야 합니다(디렉토리나 심볼릭 링크 등이 아님).
  2. omo--결과 목록을 수정 시간순으로 최신순으로 정렬 (정렬)합니다.

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 아래의 첫 번째 파일 이름에는 treewith 로 표시되는 개행 문자가 있습니다 \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:])

관련 정보