답변:
mv
디렉토리를 병합하거나 덮어 쓸 수없는 경우 --force
옵션을 사용하더라도 "mv : 'a'를 'b'로 이동할 수 없습니다 : 디렉토리가 비어 있지 않습니다" 라는 메시지와 함께 실패 합니다 .
다른 도구 (예 rsync
: find
, 또는 cp
)를 사용하여이 문제를 해결할 수 있지만 그 의미를 신중하게 고려해야합니다.
rsync
합니다 (이상적으로 다른에 하나의 디렉토리의 내용을 병합 할 수 있습니다 --remove-source-files
(1 개) 안전에만 성공적으로 전송 된 그 소스 파일을 삭제하는 옵션, 그리고 보통의 허가 / 소유 / 시간 보존 옵션을 사용하여 -a
당신이 원하는 경우) rsync
의 --link-dest=DIR
및 (가능한 대신 복사 파일 내용의 하드 링크 생성하기) 옵션을 --remove-source-files
일반에 대한 의미와 매우 유사 얻을 수를 mv
. --link-dest
대한 절대 경로 (또는 대상 에서 소스 까지의 상대 경로)를 제공해야 합니다 .
… 그러나 이것은 의도하지 않은 방식으로 (합병증을 유발하거나 유발하지 않을 수 있음) 사용하고 있으며 소스에 대한 절대 경로를 알고 (또는 결정하는) 필요 하며 빈 디렉토리 구조를 다시 정리합니다. 당 1 .--link-dest
--link-dest
find
개별적 실제 파일을 이동 대상에서 소스 디렉토리 구조를 다시 순차적으로 cp
하드 링크를 만들 수 있습니다 병합과 매우 유사한 결과를 생성, (단순히 같은 기존 파일에 추가 포인터를 넣어) mv
(만 포인터가 생성되고 실제 데이터를 복사 할 수 없습니다 때문에 매우 IO-효율적입니다) 이러한 해결 방법 (있는 경우) 중 적절한 것은 사용 사례에 따라 크게 다릅니다.
항상 그렇듯이 이러한 명령을 실행하고 백업을하기 전에 생각하십시오.
1 : rsync --remove-source-files
디렉토리를 삭제하지 않으므로 find -depth -type d -empty -delete
빈 소스 디렉토리 트리를 제거하려면 나중에 같은 작업을 수행해야합니다 .
mv
데비안에서 사용하는 구현을 - 강조가에있는 시도 맨 페이지가이 문제를 언급하지 않기 때문에 ...
--delete
파일 만 삭제합니다 .
-H
함수를 사용하여 하드 링크를 유지 하거나을 사용하여 대상의 파일을 하드 링크 할 수 있습니다 --link-dest
. 그러나 사용하기 전에 매뉴얼 페이지를 참조하십시오.
rsync -av /source/ /destination/
(after checking)
rm -rf /source/
--remove-source-files
성공적으로 전송 된 파일 만 제거 할 수 있다는 장점이 있으므로 find
빈 디렉토리를 제거 하는 데 사용할 수 있으며 rsync
출력 을 확인하지 않고도 전송되지 않은 모든 항목이 남습니다 .
cp 명령 의 -l
옵션을 사용하면 전체 데이터 사본 대신 동일한 파일 시스템에 파일의 하드 링크 가 작성 됩니다. 다음 명령은 폴더 를 이미 이름이있는 디렉토리를 포함하는 상위 폴더 ( )에 복사합니다 .source/folder
destination
folder
cp -rl source/folder destination
rm -r source/folder
필요에 따라 -P
( --no-dereference
-심볼릭 링크를 역 참조하지 않음) 또는 -a
( --archive
-모든 메타 데이터 유지, -P
옵션 포함)을 사용할 수도 있습니다 .
cp
하기 rsync
때문에 그보다는 오히려 cp
.
cp
의 작업 시간과 의 병합 능력을 얻습니다 mv
.
-n
mv /fs1/file /fs2/
(파일 시스템에서)를 복사 한 후 삭제를 수행합니다.
mv
"효율적으로"또는 호출하지 않더라도 작동 하지만 (대상 디렉토리가 존재하지 않는 경우) 작동하지 않습니다 cp -rl
.
다음 4 단계를 권장합니다.
cd ${SOURCE};
find . -type d -exec mkdir -p ${DEST}/\{} \;
find . -type f -exec mv \{} ${DEST}/\{} \;
find . -type d -empty -delete
또는 더 나은 방법은 mv
다음 과 유사한 의미를 구현하는 스크립트입니다 .
#!/bin/bash
DEST="${@:${#@}}"
ABS_DEST="$(cd "$(dirname "$DEST")"; pwd)/$(basename "$DEST")"
for SRC in ${@:1:$((${#@} -1))}; do (
cd "$SRC";
find . -type d -exec mkdir -p "${ABS_DEST}"/\{} \;
find . -type f -exec mv \{} "${ABS_DEST}"/\{} \;
find . -type d -empty -delete
) done
rsync -u
(최신 버전의 경우에만 업데이트) 와 동등한 작업을 수행하려는 경우 mv
(일부 버전에서는) -u
옵션을 사용할 수도 있습니다 . 그러나이 경우 비어 있지 않은 소스 디렉토리와 비어있는 디렉토리를 삭제하여 소스 트리의 파일이 최신이 아닌 경우를 포함 할 수 있습니다. @ schuess : 필요한 경우 여러 개의 SOURCE 인수가있을 수 있습니다.
디렉토리를 병합하는 방법은 다음과 같습니다. 파일을 복사 한 다음 삭제하는 대신 파일 이름을 변경하기 때문에 rsync보다 훨씬 빠릅니다.
cd source; find -type f -print0 | xargs -0 -n 1 -I {} mv '{}' 'dest/{}'
dest
이 이미와 이름이 같은 디렉토리 인 경우 명령이 실패 source
합니다. 그리고 파일은로 이동합니다 dest
에 인 source
. 이 명령은 더 이상 아무것도하지 않습니다mv source/* source/dest/.
가장 순수한 사본의 경우 tar (-) B blockread copy 방법을 사용합니다.
예를 들어, 소스 경로 내에서 (필요한 경우 'cd') :
tar cBf - <sourcefolder> | (cd /your/target/folder ; tar xBf -)
소유자와 권한이 그대로있는 소스 트리의 정확한 사본이 생성됩니다. 대상 폴더가 있으면 데이터가 병합됩니다. 이미 존재하는 파일 만 덮어 씁니다.
예:
$ cd /data1/home
$ tar cBf - jdoe | (cd /data2/home ; tar xBf -)
복사 작업이 성공하면 소스 ( rm -rf <source>
)를 제거 할 수 있습니다 . 물론 이것은 정확한 이동이 아닙니다. 소스를 제거 할 때까지 데이터가 복사됩니다.
옵션으로 -v를 사용하여 자세한 내용을 볼 수 있습니다 (복사중인 파일을 화면에 표시). tar cBvf -
c
: 창조하다B
: 전체 블록 읽기 (파이프 읽기 용)v
: 자세한f
: 쓸 파일x
: 추출-
: stdout / stdinsourcefolder
또한 일 수있다 *
(현재 폴더에 아무것도)
f -
tar로 지정 하는 것은 일반적으로 불필요합니다. 기본값은 stdin / write에서 stdout으로 읽는 것입니다.
여기 나를 위해 일한 스크립트가 있습니다. rsync보다 mv를 선호하므로 Jewel과 Jonathan Mayer의 솔루션을 사용합니다.
#!/bin/bash
# usage source1 .. sourceN dest
length=$(($#-1))
sources=${@:1:$length}
DEST=$(readlink -f ${!#})
for SRC in $sources; do
pushd $SRC;
find . -type d -exec mkdir -p ${DEST}/{} \;
find . -type f -exec mv {} ${DEST}/{} \;
find . -type d -empty -delete
popd
done
cp 또는 rsync와 같은 명령을 사용하는 것은 좋지 않습니다. 큰 파일의 경우 시간이 오래 걸립니다. mv는 파일을 물리적으로 복사하지 않고 inode 만 업데이트하기 때문에 훨씬 빠릅니다. 더 나은 옵션은 운영 체제의 파일 관리자를 사용하는 것입니다. Opensuse의 경우 Konquerer라는 파일 관리자가 있습니다. 실제로 복사하지 않고 파일을 이동할 수 있습니다. Windows에서와 같이 "잘라 내기 및 붙여 넣기"기능이 있습니다. 디렉토리 A에서 모든 서브 디렉토리를 선택하십시오. 동일한 이름의 서브 디렉토리를 포함 할 수있는 디렉토리 B를 마우스 오른쪽 단추로 클릭하고 "이동"하십시오. 그것들을 병합합니다. 이름이 같은 파일을 덮어 쓰거나 이름을 바꾸려는 옵션도 있습니다.
mv
는 사용될 때 어떤 일이 발생하는지 묻습니다 .
파이썬 솔루션
만족스러운 기존 솔루션을 찾을 수 없으므로 빠른 Python 스크립트를 작성하여이를 달성하기로 결정했습니다.
특히이 방법은 소스 파일 트리를 한 번만 위로 올라가므로 효율적입니다.
또한 파일 덮어 쓰기 처리와 같은 항목을 원하는대로 신속하게 조정할 수 있습니다.
용법:
move-merge-dirs src/ dest/
모든 내용을 이동 src/*
로를 dest/
하고 src/
사라집니다.
이동 병합 디렉토리
#!/usr/bin/env python3
import argparse
import os
def move_merge_dirs(source_root, dest_root):
for path, dirs, files in os.walk(source_root, topdown=False):
dest_dir = os.path.join(
dest_root,
os.path.relpath(path, source_root)
)
if not os.path.exists(dest_dir):
os.makedirs(dest_dir)
for filename in files:
os.rename(
os.path.join(path, filename),
os.path.join(dest_dir, filename)
)
for dirname in dirs:
os.rmdir(os.path.join(path, dirname))
os.rmdir(source_root)
if __name__ == '__main__':
parser = argparse.ArgumentParser(
description='Move merge src/* into dest. Overwrite existing files.'
)
parser.add_argument('src_dir')
parser.add_argument('dest_dir')
args = parser.parse_args()
move_merge_dirs(args.src_dir, args.dest_dir)
참조 : https : //.com/questions/22588225/how-do-you-merge-two-directories-or-move-with-replace-from-the-windows-command
파일 및 폴더를 다른 대상으로 이동하는 명령입니다.
$ mv /source/path/folder /target/destination/
기억하십시오 : mv
폴더가 b̲e̲i̲n̲g m̲e̲r̲ge̲d̲ (예 : 동일한 이름을 가진 다른 폴더가 대상에 이미 존재 함)이고 d̲e̲s̲t̲i̲n̲a̲t̲i̲o̲n̲ o̲n̲e̲ i̲s̲ n̲o̲t̲ e̲m̲pt̲y 이면 명령이 작동 하지 않습니다 .
mv : '/ source / path / folder'를 '/ target / destination / folder'로 이동할 수 없습니다 : 디렉토리가 비어 있지 않습니다
대상 폴더가 비어 있으면 위의 명령이 제대로 작동합니다.
따라서 두 경우 모두 두 폴더를 병합하려면 두 가지
명령으로 수행하십시오.
$ cp -rf /source/path/folder /target/destination/
$ rm -rf /source/path/folder
또는 일회성 명령으로 두 가지를 결합하십시오.
$ cp -rf /source/path/folder /target/destination/ && rm -rf /source/path/folder
mv = 이동
cp = 복사
rm = 제거디렉토리 (폴더)의 경우 -r
-f 강제 실행
mv
. 이 대답은 더 넓은 진실로 더 나을 것입니다. Linux, BSD 및 "real"Unix 또는 POSIX 또는 SUS의 참조.