파일 목록 복사


35

파일에 공백으로 구분 된 파일 목록이 있습니다 list.txt. 새 폴더에 복사하고 싶습니다.

나는 노력했다 :

cp `cat list.txt` new_folder

그러나 작동하지 않았습니다.

어떻게 하시겠습니까?

최신 정보:

모든 흥미로운 답변에 감사드립니다. 나는 그렇게 많이 요구하지 않았다 :)

위의 솔루션을 두 번 시도한 후에 cp는 폴더 new_folder가 아직 없기 때문에 사용법 도움말 이 인쇄 된 것 같습니다 ! 죄송합니다. 어리석은 실수 인 것 같습니다 ... 이전에 폴더를 만들면 작동합니다.

그러나 나는 당신의 모든 답변과 해결책에서 많은 것을 배웠습니다. 시간을내어 작성해 주셔서 감사합니다.


한 가지 명확한 점을 알려 드리겠습니다. 목록에는 모든 파일 이름이 한 줄에 공백으로 구분되어 있습니까? 아니면 이름이 각각 별도의 줄에 있습니까?
Telemachus

하나의 석회에 모두 공간으로 분리되어 있습니다. 더그의 해결책은 효과가 있었다 :) 답변 주셔서 감사합니다.
클라우스

재밌 네요 ... 각 이름이 별도의 줄에있는 줄로 솔루션을 테스트했습니다.
Doug Harris

"작동하지 않았다"는 의미가 없습니다. 정확히 어떻게 작동하지 않았습니다. 그것은 나를 위해 잘 작동합니다.
추후 공지가있을 때까지 일시 중지되었습니다.

죄송합니다 : cp 사용법 도움말을 보여주었습니다. 위의 내 업데이트를 참조하십시오.
클라우스

답변:


34

xargs를 사용해보십시오 :

cat list.txt | xargs -J % cp % new_folder

최신 정보:

GNU / Linux 버전과 다른 버전의 OS X에서이 작업을 수행했습니다. xargs에서 제공하는 GNU의 findutils의는 없습니다 -J하지만이 -I(데니스 윌리엄슨 코멘트에서 지적)과 유사하다. xargs를의 OS X 버전은 모두 가지고 -I-J약간 다른 행동을 가지고있는 - 중이 원래의 질문에 대해 작동합니다.

$ cat list.txt
one
two.txt
three.rtf

$ cat list.txt | xargs -J % echo cp % new_folder
cp one two.txt three.rtf new_folder

$ cat list.txt | xargs -I % echo cp % new_folder
cp one new_folder
cp two.txt new_folder
cp three.rtf new_folder

3
내가 xargs없는 -J것이이 -I같은 일을 보인다. 어떤 버전 xargs과 어떤 OS / 분배가 있습니까?
추후 공지가있을 때까지 일시 중지되었습니다.

나는 이것을 Mac OS X 10.6 (일명 snow leopard)에서 테스트 했으므로 xargs 버전은 OS와 함께 제공됩니다. Running xargs --version은 사용 오류 메시지를 반환합니다. 아마도 xargs의 BSD 버전 일 것입니다. 의 사용 -I-J미묘하게 다릅니다. 좋은 형식의 예제로 답변을 업데이트하겠습니다.
Doug Harris

네, 저는 Mac OSX 10.6을 사용하고 있습니다. 대한 정밀도 주셔서 감사 -J하고 -I:)
클라우스

echo를 사용하여 명령을 실행하기 전에 확인하는 것이 좋습니다.
Liam

1
필요한 변경 사항만으로 위의 동일한 명령을 사용하여 파일을 디렉토리와 하위 디렉토리를 작성하고 슬래시로 구분하여 복사하는 방법은 무엇입니까?
Vicky Dev

54

전혀 필요하지 않습니다 cat:

xargs -a list.txt cp -t new_folder

또는 긴 옵션을 사용하는 경우 :

xargs --arg-file=list.txt cp --target-directory=new_folder

다음은 일부 셸 버전입니다. forOP는 파일 이름이 공백으로 구분되도록 지정했기 때문에 일부 변수는 따옴표가 없거나 루프가 사용됩니다. 이러한 기술 중 일부는 파일 이름에 공백이 포함 된 줄당 파일 이름 입력에 작동하지 않습니다.

세게 때리다:

for file in $(<list.txt); do cp "$file" new_folder; done

또는

cp $(<list.txt) new_folder

sh (또는 Bash) :

# still no cat!
while read -r line; do for file in $line; do cp "$file" new_folder; done; done < list.txt

또는

# none here either
while read -r line; do cp $line new_folder; done < list.txt

또는

# meow
for file in $(cat list.txt); do cp "$file" new_folder; done

또는

# meow
cp $(cat list.txt) new_folder

멍청한 질문 : 왜 -t필요한가 xargs -a list.txt cp -t new_folder?
Yibo Yang

1
@YiboYang :의 -t옵션입니다 cp. 모든 소스 인수를 지정된 대상 디렉토리에 복사합니다. 여기에서 xargs명령 에 의해 추가 된 소스 앞에 대상을 지정할 수 있습니다 .
추후 공지가있을 때까지 일시 중지되었습니다.

이것은 유용하지만 list.txt에 혼합 파일 및 폴더 경로가 포함되어 있으면 어떻게됩니까? 이 경우 명령이 제대로 작동하지 않습니다. "omitting directory ..."를보고하고 -R을 cp 명령에 지정하면 목록의 첫 번째 파일이 발견되는 즉시 "is not a directory"오류가보고됩니다.
Bemipefe

7

나는 여기에 당황스럽게 반올림 대답을했지만, Denis의 대답 은 내가 가장 기본적인 것을 놓쳤다는 것을 나에게 상기시켰다. 그래서 원래 답변을 삭제했습니다. 아무도 이후하지만 말했다 이 매우 기본적인 것, 나는 그것의 가치는 여기에 넣어 생각합니다.

원래 질문은 "공백으로 구분 된 파일 이름 목록이있는 텍스트 파일이 있습니다. 파일을 하나의 대상 디렉토리에 복사하는 방법"입니다. 처음에는 파일에서 특정 방식으로 항목을 추출해야한다고 생각하기 때문에 까다 롭거나 복잡해 보일 수 있습니다. 그러나 쉘이 명령 행을 처리 할 때 가장 먼저하는 일은 인수 목록을 토큰으로 분리 하고 (아무도 말하지 않은 비트는) 별도의 토큰을 공백 으로 만드는 것 입니다. 개행은 또한 토큰을 분리하므로 개행으로 분리 된 목록을 사용하는 Doug Harris의 테스트 결과는 동일합니다. 즉, 쉘은 공백으로 구분 된 목록을 예상하고 이미 처리 할 수 ​​있습니다.

따라서 여기서해야 할 일은 공백으로 구분 된 목록 (이미 가지고 있음)을 명령의 올바른 위치에 두는 것입니다. 당신의 명령은 이것에 약간의 변형입니다 :

cp file1 file2 file3...file# target

유일한 주름은 텍스트 파일에서 1부터 #까지의 파일 목록을 가져 오려는 것입니다.

Dennis가 그의 의견에서 지적했듯이 원래 시도 ( cpcat list.txt new_folder)는 이미 작동했을 것입니다. 왜? 내부 명령 cat list.txt은 셸에서 먼저 처리되고으로 확장되기 file1 file2 file3...file#때문에 셸은 명령의 해당 부분에서 정확히 예상하고 원하는 것입니다. 작동하지 않으면 (1) 오타가 있거나 (2) 파일 이름이 다소 이상했습니다 (공백 또는 기타 특이한 문자가 있음).

모든 Dennis의 답변이 작동하는 이유는 단순히 작업에 필요한 파일 목록을 제공 cp하여 해당 목록을 전체 명령에 속하는 위치에 배치하기 때문입니다. 다시 말하지만 명령 자체는 다음과 같습니다.

cp list-of-files target_directory

이 버전에서이 모든 것이 어떻게 결합되는지 쉽게 알 수 있습니다.

cp $(<list.txt) new_folder

$()쉘이 괄호 안에서 명령을 실행 한 다음 더 큰 행의 해당 지점에서 출력을 대체합니다. 그런 다음 쉘은 전체 라인을 실행합니다. 그건 그렇고, $()당신이 이미 백틱으로하고있는 것의 더 현대적인 버전입니다 (`). 다음 : <파일 리디렉션 연산자입니다. 쉘에 내용 list.txt을 표준 입력 으로 덤프하도록 지시합니다 . $()비트가 먼저 처리 되므로 다음 과 같은 단계가 수행됩니다.

  1. cp $(<list.txt) new_folder # split line into three tokens: cp, $(<list.txt), new_folder
  2. cp file1 file2 file3...file# new_folder # substitute result of $(<list.txt) into the larger command

분명히 2 단계는 단순히 원하는 일반적인 cp명령입니다.

나는이 (아마도 매우 죽은) 말을 많이 때리고 있다는 것을 알고 있지만 그만한 가치가 있다고 생각합니다. 쉘이 명령을 처리하는 방법을 정확하게 이해 하면 명령을 더 잘 작성하고 단순화 할 수 있습니다. 또한 문제가 숨어있을 가능성이있는 곳을 보여줍니다. 이 경우, 예를 들어, 첫 번째 질문은 재미있는 파일 이름이나 가능한 오타에 관한 것이 었습니다. 곡예가 필요하지 않았습니다.


@Klaus 천만에요. 솔직히 말해서, 나는 Dennis의 답변을 읽고 문제의 핵심 부분을 완전히 놓친 것을 깨닫고 나 자신에 대해 대부분 화가났다. 원하는 솔루션도 있습니다.
Telemachus

이것은 매우 오래된 대답이지만 폴더 구조를 다시 만들어야하는 경우 --parents플래그 가 필요합니다 . -v복사 된 내용에 대한 자세한 정보를 얻을 수 있습니다 . 권한을 유지하려면 -a또는 -p플래그 가 필요합니다 . 즉 cp --parents -av $(<list.txt) new_folder. 이것은 파일 목록이 실제로 모든 파일이라고 가정하고, 그렇지 않으면 -r반복하기 위해 플래그가 필요할 수도 있습니다 .
dhaupin

@dhaupin 사실, OP는 그가 macOS에 있었다고 말합니다. 따라서 가치가있는 것은 --parents깃발이 존재하지 않습니다. 그들의 (BSD 파생) 버전은 cpGNU 스타일의 긴 옵션이 아닌 짧은 옵션 만 제공합니다. BSD 스타일의 cp경우 재귀 복사 플래그는 소문자 -R가 아닌 대문자입니다.
Telemachus
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.