디렉토리에 파일 이름별로 정렬 된 많은 파일이 있습니다. 최종 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 호환 쉘로 이식 가능해야합니다. 두 가지 방법에 대한 참고 사항 :
-
cp
논쟁 을 이끌cp --
거나.
점 하나 또는/
각 이름의 머리 중 하나를 얻는 것이 중요합니다 . 이를 수행하지 않으면 옵션으로 해석되어 작업이 실패하거나 의도하지 않은 결과를 초래할 수있는 첫 번째 인수-
에서 선행 대시가 발생할 위험이 있습니다cp
.- 현재 디렉토리를 소스 디렉토리로 사용하더라도 …
set -- ./*
또는array=(./*)
.
- 현재 디렉토리를 소스 디렉토리로 사용하더라도 …
-
두 가지 방법을 모두 사용하여 제거하려고 시도하는 것처럼 최소한 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"