여러 디렉터리에 여러 파일이 있는 디렉터리 구조가 있습니다 .txt
. .txt
이 모든 파일을 특정 디렉터리에 복사 하고 싶습니다 . 아래에 내 디렉토리 구조를 지정했습니다.
Dir_1
a.txt
x.doc
b.txt
Dir_2
c.txt
Dir_3
d.txt
e.txt
y.doc
.txt
모든 파일을 디렉토리에 복사하려면 ~/alltxt
다음 cp
명령을 사용합니다.
find . -name "*.txt" -exec cp {} ~/alltxt/ \;
그것은 아주 잘 작동합니다. 이제 내 디렉토리는 alltxt
아래와 같습니다.
alltxt
a.txt
b.txt
c.txt
d.txt
e.txt
.txt
하지만 변경된 파일만 해당 폴더로 바꾸고 싶다는 것을 알았습니다 . 그래서 rsync
다음과 같은 명령어를 사용하면 이 작업을 수행 할 수 있다는 것을 알게 되었습니다 .
find . -name '*.txt' -exec rsync -R {} ~/alltxt/ \;
.txt
그러나 아래와 같이 폴더별로 파일을 복사 합니다 .
alltxt
Dir_1
a.txt
x.doc
b.txt
Dir_2
c.txt
Dir_3
d.txt
e.txt
y.doc
rsync
하지만 내 명령처럼 작동하도록 명령을 어떻게 변경할 수 있습니까 cp
?
답변1
rsync
--existing
대상에 아직 존재하지 않는 파일을 복사하지 않는 플래그가 있습니다 .
find . -type f -name '*.txt' -exec rsync --existing {} "$HOME/alltxt/" ';'
-type f
또한 다음 항목 find
만 찾도록 추가했습니다.일반 파일, 이 경우에는 유용하지 않다고 생각하기 때문에 -R
플래그( --relative
) 를 제거했습니다 (이 플래그를 사용하면 대상에 하위 디렉토리가 생기는 이유이기도 합니다). rsync
나는 또한 그것이 더 좋아 보인다고 생각하기 때문에 $HOME
대신 사용합니다.~
소유권과 수정 시간 등을 보존하기 위해 호출에 -a
( --archive
)를 추가할 수도 있습니다.rsync
비슷한 방법이지만 cp
대신 사용됩니다 rsync
.
find . -type f -name '*.txt' \
-exec sh -c 'for n; do d="$HOME/alltxt/${n##*/}"; [ -f "$d" ] && cp "$n" "$d"; done' sh {} +
이는 모든 .txt
파일을 찾고 짧은 쉘 스크립트를 호출합니다.
for n; do
d="$HOME/alltxt/${n##*/}"
[ -f "$d" ] && cp "$n" "$d"
done
이 루프는 여기에서 많은 .txt
파일을 가져옵니다 find
. 이러한 각 이름에 대해 에 n
대상 파일 경로를 생성하고 d
해당 경로가 기존 일반 파일을 참조하는지 확인하고, 그렇다면 지정된 파일을 거기에 복사합니다.
대상 파일이 존재하고 발견된 파일보다 오래된 경우 [ -f "$d" ]
대신 이 테스트를 사용할 수 있습니다 . [ "$d" -ot "$n" ]
이는 비표준 테스트이지만 대부분의 쉘에서 지원됩니다.
변수 대체는 ${n##*/}
경로에서 디렉토리를 제거하여 (basename) 이 n
됩니다 . 로 대체할 수 있습니다 ../some/path/file.txt
file.txt
$(basename "$n")
답변2
shopt -s globstar
cp --update --target-directory targetDirectory sourceRootDir/**/*.txt
어디:
shopt -s globstar
**
모드를 포함하여 확장된 와일드카드 옵션을 설정합니다.--target-directory
또는-t
복사할 대상 디렉터리를 제공합니다(이는 모든 인수 끝에 지정할 수도 있지만 일반적으로 스크립트에 넣는 것이 더 읽기 쉽습니다).--update
또는 대상이 오래되었거나 존재하지 않는 경우에만 파일을 복사하세요-u
.cp