폴더 구조 병합

폴더 구조 병합

다음과 같은 폴더 구조가 있습니다.

├── foo1
│   ├── bar1.txt
│   └── bar2.txt
├── foo2
│   ├── bar3.txt
│   └── bar4 with a space.txt
└── foo3
    └── qux1
        ├── bar5.txt
        └── bar6.txt

각 폴더 수준 사이에 밑줄을 사용하여 이를 평면화하고 싶습니다.

├── foo1_bar1.txt
├── foo1_bar2.txt
├── foo2_bar3.txt
├── foo2_bar4 with a space.txt
├── foo3_qux1.bar6.txt
└── foo3_qux1_bar5.txt

주위를 둘러보았지만 작동하는 솔루션을 찾지 못했습니다. 대부분 내 문제에는 두 가지 특수성이 있기 때문이라고 생각합니다. 루트 폴더 내부에 폴더 수준이 두 개 이상 있을 수 있고 일부 파일에 공백이 있을 수 있기 때문입니다.

Bash에서 이를 수행하는 방법을 아시나요? 감사해요!

편집하다: 글렌 잭맨이 제안한 답변을 실행하면 다음과 같은 결과를 얻습니다.

여기에 이미지 설명을 입력하세요

첫 번째 수준 폴더에는 두 개의 밑줄이 있습니다. 이것을 피하는 방법이나 밑줄 하나만 사용하도록 이름을 바꾸는 방법에 대한 아이디어가 있습니까? 감사해요.

답변1

find */ -type f -exec bash -c 'file=${1#./}; echo mv "$file" "${file//\//_}"' _ '{}' \;

echo만족스러우면 제거하세요 . 작동하는 것입니다. echo'ed 명령이 따옴표를 표시하지 않는다는 점에 대해 걱정하지 마십시오. 스크립트는 공백이 있는 파일을 적절하게 처리합니다.

현재 비어 있는 하위 디렉터리를 제거하려면 다음을 수행하세요.

find */ -depth -type d -exec echo rmdir '{}' \; 

답변2

Perl의 이름 바꾸기 사용:

find . -depth -type f -exec rename 's@(?<!\.)/@_@g' -- {} \;

산출

$ find -type f
./foo2_bar4 whit a space.txt
./foo3_qux1_bar6.txt
./foo2_bar3.txt
./foo3_qux1_bar5.txt
./foo1_bar2.txt
./foo1_bar1.txt

메모

  • 나는부정적인 뒷모습 (?<!\.)먼저 만지지 말라고./
  • 나는 빈 디렉토리를 유지합니다. 자유롭게 다음을 수행하십시오.

    find . -depth -type d -exec rm {} \;

경고이 작업을 수행할 수도 있고 수행하지 못할 수도 있는 같은 이름의 다른 도구가 있으므로 주의하세요.

다음 명령을 실행하면 ( GNU)

$ file "$(readlink -f "$(type -p rename)")"

그리고 당신은 다음과 같은 결과를 얻었습니다

.../rename: Perl script, ASCII text executable

다음을 포함하지 않음:

ELF

그렇다면 이것이 올바른 도구인 것 같습니다 =)

Debian그렇지 않은 경우 다음과 같은 파생 항목을 기본값(일반적으로 이미 적용됨)으로 설정합니다 Ubuntu.

$ sudo update-alternatives --set rename /path/to/rename

( /path/to/rename명령 경로로 바꾸십시오 perl's rename.


이 명령이 없으면 패키지 관리자를 검색하여 설치하거나수동으로 해라


마지막으로 이 도구는 원래 Perl의 아버지인 Larry Wall이 작성했습니다.

답변3

~와 함께pax...

pax -Xrwls '|/|_|g' */ "$PWD"

그러면 현재 디렉토리 _에 로 대체된 하위 디렉토리의 모든 파일에 대한 하드링크가 생성됩니다 /. 그런 다음 결과를 검사하고 다음을 사용하여 모든 하위 디렉터리를 제거할 수 있습니다.

rm -rf */

...결과가 마음에 드는지 확인하고 나면.

답변4

아래 명령으로 시도해 볼 수 있습니다.

$ find -type f -exec bash -c 'mv $0 $(echo $0|sed "s/\//_/2")' {} \;

위 명령은 파일을 이동하고 나중에 제거할 수 있는 디렉토리는 그대로 유지됩니다.

$ ls
foo1_bar1.txt  foo1_bar2.txt  foo2_bar3.txt  foo2_bar4.txt  foo3_bar5.txt  foo3_bar6.txt

관련 정보