중첩 된 디렉토리 평탄화 |

이것은 아마도 매우 간단하지만 이해할 수 없습니다. 다음과 같은 디렉토리 구조가 있습니다 (dir2는 dir1 안에 있습니다).

/dir1
    /dir2
       |
        --- file1
       |
        --- file2

dir2가 아닌 dir1에서 file1과 file2를 얻는 방식 으로이 디렉터 구조를 ‘평평하게’하는 가장 좋은 방법은 무엇입니까?



답변

GNU find와 GNU 로이 작업을 수행 할 수 있습니다 mv.

find /dir1 -mindepth 2 -type f -exec mv -t /dir1 -i '{}' +

기본적으로 find전체 디렉토리 트리를 통과하고 -type f최상위 디렉토리 ( -mindepth 2)에 없는 각 파일 ( ) 에 대해 작동하는 방식은 원하는 디렉토리 ( ) mv로 이동합니다 -exec mv … +. -t인수 할 mv수 있습니다 당신이 필요로하는, 먼저 대상 디렉토리를 지정하기 때문에 +형태 -exec명령의 끝에 풋 모든 소스 위치. -i차종은 mv어떤 중복을 덮어 쓰기 전에 물어; -f묻지 않고 -n덮어 쓰거나 요청하거나 덮어 쓰지 않고 대체 할 수 있습니다 .

Stephane Chazelas가 지적했듯이 위의 내용은 GNU 도구 (Linux의 표준이지만 대부분의 다른 시스템은 아닙니다)에서만 작동합니다. 다음은 mv여러 번 호출하기 때문에 다소 느리지 만 훨씬 보편적입니다.

find /dir1 -mindepth 2 -type f -exec mv -i '{}' /dir1 ';'


답변

zsh에서 :

mv dir1/*/**/*(.D) dir1

**/하위 디렉토리를 재귀 적으로 탐색합니다. 글로브 한정자는 . 정규 파일과 일치하고, D(기본, 이름이 시작하는을 가진 파일이 점 파일이 포함되도록 .와일드 카드에서 제외됩니다 일치). 이후에 비어있는 디렉토리를 정리하려면 다음을 실행하십시오. rmdir dir1/**/*(/Dod)/디렉토리로 제한 od하고 일치 항목을 먼저 제거하여 dir1/dir2/dir3before 제거하십시오 dir1/dir2.

파일 이름의 총 길이가 너무 길면 명령 줄 길이에 제한이있을 수 있습니다. Zsh에는 이 제한에 영향을 미치지 않는 내장 기능이 mv있으며 rmdir이를 zmodload zsh/files사용 하려면 실행하십시오 .

POSIX 도구 만 사용 :

find dir1 -type f -exec mv {} dir1 \;
find dir1 -depth -exec rmdir {} \;

또는 (각 파일마다 별도의 프로세스를 실행할 필요가 없기 때문에 더 빠름)

find dir1 -type f -exec sh -c 'mv "$@" dir1' _ {} +
find dir1 -depth -exec rmdir {} +


답변

이것을 시도하십시오 :

cp /dir1/dir2/file{1,2} /another/place

또는 file[0-9]*subdir에서 일치하는 각 파일에 대해 :

cp /dir1/dir2/file[0-9]* /another/place

http://mywiki.wooledge.org/glob를 참조 하십시오


답변

함께 사용할 수있는 두 가지 기능을 작성했습니다 -maxdepth $VAL. 매개 변수 를 추가하여 디렉토리 수준을 제한 할 수 있습니다 .

# This scripts flattens the file directory
# Run this script with a folder as parameter:
# $ path/to/script path/to/folder

#!/bin/bash

rmEmptyDirs(){
    local DIR="$1"
    for dir in "$DIR"/*/
    do
        [ -d "${dir}" ] || continue # if not a directory, skip
        dir=${dir%*/}
        if [ "$(ls -A "$dir")" ]; then
            rmEmptyDirs "$dir"
        else
            rmdir "$dir"
        fi
    done
    if [ "$(ls -A "$DIR")" ]; then
        rmEmptyDirs "$DIR"
    fi
}

flattenDir(){
    local DIR="$1"
    find "$DIR" -mindepth 2 -type f -exec mv -i '{}' "$DIR" ';'
}

read -p "Do you wish to flatten folder: ${1}? " -n 1 -r
echo    # (optional) move to a new line
if [[ $REPLY =~ ^[Yy]$ ]]
then
    flattenDir "$1" &
    rmEmptyDirs "$1" &
    echo "Done";
fi


답변

동일한 이름의 파일을 포함하는 디렉토리를 평탄화하기위한 유스 케이스가 있었 으므로이 질문에 대한 인기있는 답변을 확장했습니다.

dir1/
├── dir2
   └── file
└── dir3
    └── file

이 경우 전달 된 -i( --interactive) 옵션 mv은 디렉토리 구조를 평탄화하고 이름 충돌을 처리하기 위해 원하는 결과를 얻지 못합니다. 그래서 단순히으로 대체 것 --backup=t(상당 --backup=numbered). 온 더 문서 -b( --backup에서 구입 가능) 옵션 https://www.gnu.org/software/coreutils/manual/coreutils.html#Backup-options .

를 야기하는:

find dir1/ -mindepth 2 -type f -exec mv -t dir1/ --backup=t '{}' +

산출량 :

dir1/
├── dir2
├── dir3
├── file
└── file.~1~


답변

tar와 zip은 둘 다 디렉토리 구조를 통합 한 다음 제거 할 수 있으므로 중첩 된 디렉토리를 신속하게 병합 할 수있었습니다.

tar -cvf all.tar *

all.tar를 새 위치로 이동 한 다음

tar -xvf all.tar --strip=4


답변