디렉토리에서 마지막 N 파일을 얻는 방법? 파일이 있습니다. 최종 N

디렉토리에 파일 이름별로 정렬 된 많은 파일이 있습니다. 최종 N (예 : N = 4) 파일을 내 홈 디렉토리에 복사하고 싶습니다. 어떻게해야합니까?

cp ./<the final 4 files> ~/



답변

이것은 bash / ksh93 / zsh 배열로 쉽게 수행 할 수 있습니다.

a=(*)
cp -- "${a[@]: -4}" ~/

공백, 탭, 줄 바꿈 또는 기타 어려운 문자가 포함되어 있더라도 숨겨지지 않은 모든 파일 이름에서 작동합니다. bash ).

작동 원리

  • a=(*)

    a모든 파일 이름으로 배열 을 만듭니다 . bash가 리턴 한 파일 이름은 알파벳순으로 정렬됩니다. (이것이 “파일 이름순”으로 의미하는 것으로 가정합니다 . )

  • ${a[@]: -4}

    배열의 마지막 4 개 요소를 반환합니다 a(배열에 4 개 이상의 요소가 포함 된 경우 bash).

  • cp -- "${a[@]: -4}" ~/

    마지막 네 파일 이름이 홈 디렉토리로 복사됩니다.

동시에 복사하고 이름을 바꾸려면

이렇게하면 마지막 네 파일이 홈 디렉토리에만 복사되고 동시에 a_복사 된 파일 이름 앞에 문자열 이 추가 됩니다.

a=(*)
for fname in "${a[@]: -4}"; do cp -- "$fname" ~/a_"$fname"; done

다른 디렉토리에서 복사하고 이름을 바꿉니다.

우리가 사용하는 경우 a=(./some_dir/*)대신 a=(*), 우리는 디렉토리의 문제는 파일 이름에 부착되어 있습니다. 한 가지 해결책은 다음과 같습니다.

a=(./some_dir/*)
for f in "${a[@]: -4}"; do cp "$f"  ~/a_"${f##*/}"; done

또 다른 해결책은 서브 쉘과 서브 쉘 cd의 디렉토리 를 사용하는 것입니다 .

(cd ./some_dir && a=(*) && for f in "${a[@]: -4}"; do cp -- "$f" ~/a_"$f"; done) 

서브 쉘이 완료되면 쉘은 원래 디렉토리로 우리를 리턴합니다.

순서가 일관성이 있는지 확인

질문은 “파일 이름으로 정렬 된”파일을 요청합니다. Olivier Dulac의 의견에 따르면, 그 순서는 로케일마다 다릅니다. 머신 설정과 관계없이 고정 된 결과를 가져야하는 경우 배열 a이 정의 될 때 로케일을 명시 적으로 지정하는 것이 가장 좋습니다 . 예를 들면 다음과 같습니다.

LC_ALL=C a=(*)

locale명령 을 실행하여 현재있는 로케일을 찾을 수 있습니다 .


답변

사용하는 경우 원하는 파일을 선택하는 소위 glob 한정자 목록을 zsh괄호 ()로 묶을 수 있습니다. 귀하의 경우에는

cp *(On[1,4]) ~/

여기에서 On파일 이름을 알파벳순으로 역순으로 정렬하고[1,4] 처음 4 개만 사용합니다.

로 일반 파일 (디렉토리, 파이프 등 제외) 만 선택하고 이름이 올바르게 시작하는 파일을 처리하기 위해 명령에 .추가 --하여 이를 더욱 강력하게 만들 수 있습니다 .cp-

cp -- *(.On[1,4]) ~

D숨겨진 파일 (도트 파일)도 고려 하려면 규정자를 추가하십시오 .

cp -- *(D.On[1,4]) ~

답변

다음은 매우 간단한 bash 명령을 사용하는 솔루션입니다.

find . -maxdepth 1 -type f | sort | tail -n 4 | while read -r file; do cp "$file" ~/; done

설명:

find . -maxdepth 1 -type f

현재 디렉토리에서 모든 파일을 찾습니다.

sort

알파벳순으로 정렬합니다.

tail -n 4

마지막 4 줄만 표시하십시오.

while read -r file; do cp "$file" ~/; done

복사 명령을 수행하는 각 줄을 반복합니다.


답변

쉘 정렬이 합리적이라면 다음과 같이하면됩니다.

set -- /path/to/source/dir/*
[ "$#" -le 4 ] || shift "$(($#-4))"
cp "$@" /path/to/target/dir

이것은 bash제공되는 특정 어레이 솔루션 과 매우 유사 하지만 POSIX 호환 쉘로 이식 가능해야합니다. 두 가지 방법에 대한 참고 사항 :

  1. cp논쟁 을 이끌 cp --거나 .점 하나 또는 /각 이름의 머리 중 하나를 얻는 것이 중요합니다 . 이를 수행하지 않으면 옵션으로 해석되어 작업이 실패하거나 의도하지 않은 결과를 초래할 수있는 첫 번째 인수 -에서 선행 대시가 발생할 위험이 있습니다 cp.

    • 현재 디렉토리를 소스 디렉토리로 사용하더라도 … set -- ./*또는 array=(./*).
  2. 두 가지 방법을 모두 사용하여 제거하려고 시도하는 것처럼 최소한 arg 배열에 많은 항목이 있는지 확인하는 것이 중요합니다. 여기서는 수학 확장으로 수행합니다. 는 shift적어도 4 개 인수 배열에 항목이있는 경우에만 발생합니다 – 단지 변화 떨어진 후 4의 흑자를 만들 그 첫번째 인수가 ..

    • 따라서 어떤 set 1 2 3 4 5경우에는 1멀리 이동 하지만 어떤 set 1 2 3경우에는 아무것도 이동하지 않습니다.
    • 예를 들어 : a=(1 2 3); echo "${a[@]: -4}"빈 줄을 인쇄합니다.

한 디렉토리에서 다른 디렉토리로 복사하는 경우 다음을 사용할 수 있습니다 pax.

set -- /path/to/source/dir/*
[ "$#" -le 4 ] || shift "$(($#-4))"
pax -rws '|.*/|new_prefix|' "$@" /path/to/target/dir

sed모든 파일 이름을 복사 할 때 스타일 대체를 적용 합니다.


답변

파일 만 있고 파일 이름에 공백이나 줄 바꿈 (및 수정하지 않은 $IFS) 또는 glob 문자 (또는 일부 구현이있는 인쇄 할 수없는 문자 ls)가 포함되어 있지 않은 .경우 다음 과 같이 시작할 수 없습니다 :

cp -- $(ls | tail -n 4) ~/

답변

이것은 루프 코드가없는 간단한 bash 솔루션입니다. 현재 디렉토리에서 대상으로 마지막 4 개의 파일을 복사하십시오.

$ find . -maxdepth 1 -type f |tail -n -4|xargs cp -t "$destdir"