와일드 카드로 여러 파일을 복사하려면 어떻게합니까?


42

ABC. *에 많은 파일이있는 폴더가 있습니다 (대략 100 개의 파일이 있습니다). 이름을 DEF로 시작하는 새 파일에 모두 복제하고 싶습니다. *

그래서 나는 원한다

ABC.Page1
ABC.Page2
ABC.Topic12
...etc

에 복사

DEF.Page1
DEF.Page2
DEF.Topic12
...etc

배치 명령으로 BASH 또는 이와 유사한 방법을 사용하는 가장 간단한 방법은 무엇입니까? sed 또는 awk 또는 xargs와 관련된 것을 생각하고 있지만 구문을 파악하는 데 어려움이 있습니다. 파이썬 스크립트를 작성할 수는 있지만 너무 복잡하지 않은 명령 줄 솔루션이 있다고 생각합니다.


훌륭한 mc파일 관리자는 이러한 종류의 대량 이름 바꾸기를 가장 광범위하게 지원합니다.
oakad

@oakad tar도 봄 닭이 아닙니다. 예를 들어 내 대답을 참조하십시오.
mikeserv

답변:


41

bash에서 이와 같은 것은 어떻습니까?

for file in ABC.*; do cp "$file" "${file/ABC/DEF}";done

cp 명령 앞에 echo를 넣어서 테스트 할 수 있습니다.

for file in ABC.*; do echo cp "$file" "${file/ABC/DEF}";done

완전한. 내가 상상했던 것보다 훨씬 간단합니다.
Octopus

대부분의 경우 충분하지만 에코를 확인하는 것이 중요합니다. 스크립트에서이 작업을 수행하지 마십시오 . 더 많은 정보를 원하시면 bash 함정을
pawel7318

@ pawel7318, 당신이 준 링크는 훌륭한 조언이지만 위에서 주어진 명령에 적용되지 않는 것 같습니다. 내가이 명령으로 볼 수있는 유일한 가장자리의 경우는 다음과 같습니다 : (1) 대상 파일이 이미 존재 여부를 확인하지 않습니다 이나 대상 파일이 이미로 존재하는 경우 디렉토리 (파일을 복사 할 것이다 현재의 이름을 유지, 디렉토리) (2) glob 확장이 단일 명령 행에 맞지 않는 파일이 너무 많은 경우.
와일드 카드

1
나는 이것을 얻는다 : cp /usr/local/lib/libboost* /usr/local/lib/libboost*echo check.
Tomáš Zato

8

많은 수의 파일로이 작업을 효율적으로 수행하려면 각 파일 cp마다 다른 프로세스를 시작하지 않는 것이 좋습니다 . 한 가지 방법은 다음을 사용하여 파일을 복사 한 다음 이름을 바꾸는 것입니다 prename( rename데비안 기반 배포판에서는 기본적으로 심볼릭 링크 됨). 이것과 리눅스 사용하기 mktemp:

tmp=$(mktemp -d --tmpdir=.)
cp ABC.* "$tmp"
prename "s:$tmp/ABC:DEF:" "$tmp/"*
rmdir "$tmp"

최신 정보

실제로 pax여기에 더 나은 방법 일 수 있습니다.

pax -rws '/^ABC/DEF/' ABC.* .

불행히도 paxPOSIX와 Linux Standard Base 모두 에 불구하고 현재 기본적으로 포함되는 배포판은 거의 없습니다.


탈출을 피하기 위해 :를 구분 기호로 사용하면 좋습니다.
Clayton Stanley

5

tar 정말 빨리 당신을 위해 이것을 할 것입니다.

테스트

먼저 2 개의 디렉토리와 10 개의 파일을 만들었습니다.

% mkdir test1 test2 ; cd test1
% for n in `seq 1 10` ; do touch ABC.file$n ; done
% ls

> ABC.file1   ABC.file2  ABC.file4  ABC.file6  ABC.file8
> ABC.file10  ABC.file3  ABC.file5  ABC.file7  ABC.file9

그런 다음 복사했습니다.

% tar -cf - ./* |\ 
    tar -C../test2 --transform='s/ABC/DEF/' -xf -
% ls ../test2

> DEF.file1   DEF.file2  DEF.file4  DEF.file6  DEF.file8
> DEF.file10  DEF.file3  DEF.file5  DEF.file7  DEF.file9

변환

따라서 GNU tarsed --transform=EXPRESSION파일 이름 바꾸기를 허용합니다 . 파일의 일부만 이름을 바꿀 수도 있습니다. 예를 들어 :

% tar -cf - ./* |\ 
    tar -C../test2 --transform='s/ABC\(.*[0-5]\)/DEF\1/' -xf -
% ls ../test2

> ABC.file6  ABC.file8  DEF.file1   DEF.file2  DEF.file4
> ABC.file7  ABC.file9  DEF.file10  DEF.file3  DEF.file5

이것이 한 가지 장점입니다.

흐름

또한이 tar프로세스 는 두 개의 프로세스에 불과 하며 파일 수에 관계없이 변경되지 않습니다.

tar | tar

tar당신이 원하는만큼 최적화되어 있습니다. 이것은 문제 인수 수 또는 폭주 하위 프로세스를 갖지 않습니다. 이것은 단지 A> B 입니다.

인수

나는 두 tar프로세스 사이에 7 개의 구별 된 인수를 사용한다 . 가장 중요한 것이 먼저 여기에 나열됩니다.

-표준 출력 / 표준 입력 -이 정보 용 tar그것으로 하나의 입력 또는 출력을 스트리밍한다으로부터 또는 stdin/stdout어느 올바르게은 건물 또는 아카이브 추출되어 있는지의 여부에 따라 해석된다.

-c생성 -이 이야기 tar아카이브를 구축 할 수 있습니다. 다음 주장 tar은 ...

-f파일 - 테이프 장치 등이 아닌 객체 tar로 작업하도록 지정합니다 file. 그리고 위에서 언급했듯이 작업 할 파일은 stdin/stdout다시 말해 우리의 파일 |pipe입니다.

./*모든 $ PWD / 파일 - 너무 많은 아카이브 인수가 있으므로, 먼저 것을 제외하고 여기에 설명하지 -다음 ./*.

... 그리고 반대편에 |pipe...

-C디렉토리 변경 - tar다른 조치를 수행하기 전에 내가 지정한 디렉토리로 변경해야하므로 효과적으로 cd ../test2추출하기 직전에 변경 해야합니다.

--transform='s/ed/EXPR/'-이미 언급했듯이 이름을 바꿨습니다. 그러나 문서는 모든 sed표현을 취할 수 있음을 나타냅니다 //flag.

-xextract-tar 대상 디렉토리로 변경 한 후 이름 바꾸기 지시 사항을 수신하면 -f - |pipe아카이브 파일 에서 현재 디렉토리로 모든 파일의 추출을 시작하도록 지시 합니다. 미스터리가 없습니다.


1
pax이 질문에 대한 해결책 은 다음과 같습니다 . 나는 그것을 나의 대답에 추가 할 것이지만, 나는 그것이 여기에 더 적합하다고 생각한다pax -rws '/^ABC/DEF/' ABC.* .
Graeme

@Graeme-woah-그게 더 나아! 사람, 그것은 진주 이름 바꾸기에서 지옥을 이겼습니다! 이것을 paxPOSIX에 명시 해야 합니다 pax.
mikeserv

paxPOSIX 일 수도 있지만 불행히도 기본적으로 거의 설치되지 않습니다.
Graeme

4

덜 표준적인 도구를 사용하는 것이 마음에 들지 않으면 이런 종류의 작업을 위해 작성된 mmv (질량 이동)를 사용하는 것이 좋습니다 . mcp제품군의 일부인 (대량 복사)를 사용하면 간단히 할 수 있습니다.

mcp "ABC.*" "DEF.#1"

다운로드 패키지를 찾는 것은 쉽지 않습니다. 집에서 컴파일하기 위해 현재 데비안 패키지 (Arch에서도 AUR에서 사용)는 여기 에서 찾을 수 있습니다 .


상자에서 우분투 15.10에 설치apt-get install mmv
Thufir

2

zsh에서 다음 행을 다음에 넣으십시오 .zshrc.

autoload -U zmv
alias zmv='noglob zmv'
alias zcp='zmv -C'
alias zln='zmv -L'

그런 다음 명령 행에서 다음을 실행할 수 있습니다.

zcp 'ABC(.*)' 'DEF$1'

또는 단순히

zcp -W ABC.* DEF.*

zsh가 설치되어있는 한 다른 쉘에서 :

zsh -c 'autoload zmv; noglob zmv -CW ABC.* DEF.*'

1

당신은 이것을 할 수 있습니다 :

for i in ABC.*; do cp {ABC,DEF}."${i#*.}"; done

보이지 않는 것이있을 수 있지만 여러 목적지를 어떻게 설정합니까? 각 루프를 얻기 위해 for 루프를 사용하고 있습니다. 미리 코드를 테스트했으며 예상대로 작동하므로 설명에 감사드립니다.
사라 Fauzia

그건 내 잘못이야, 네 대답을 잘못 읽었 어. :-)
Chris Down

"${i#*.}"비트를 어떻게 읽어야 합니까?
dumbledad

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.