답변:
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 ';'
-exec +
다수의 프로세스를 실행하지 않도록 사용 하도록 편집되었습니다.mv
mv
대상은 최종 인수로 필요하지만 +는 최종 인수로 소스를 갖습니다. 심지어 늘 찾기 동의 구문을 당신은 (그것을 변경 find: missing argument to `-exec'
)
mv
이 -t
우리가 사용할 수있는, 그래서 나는 그로 변경됩니다.
find
은 기본적으로 숨겨진 (도트) 파일을 인쇄합니다. 깊이는 찾으려는 디렉토리를 기준으로합니다.
find ./dir -mindepth 2 -type f -exec mv -f '{}' ./dir ';'
중복을 재정의하는 경우
zsh에서 :
mv dir1/*/**/*(.D) dir1
**/
하위 디렉토리를 재귀 적으로 탐색합니다. 글로브 한정자는 .
정규 파일과 일치하고, D
(기본, 이름이 시작하는을 가진 파일이 점 파일이 포함되도록 .
와일드 카드에서 제외됩니다 일치). 이후에 비어있는 디렉토리를 정리하려면 다음을 실행하십시오. rmdir dir1/**/*(/Dod)
— /
디렉토리로 제한 od
하고 일치 항목을 먼저 제거하여 dir1/dir2/dir3
before 제거하십시오 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
{}
실제 문제 에 사용하려면 많은 파일이 있어야합니다 .
함께 사용할 수있는 두 가지 기능을 작성했습니다 -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~