주어진 이름을 가진 디렉토리를 찾고 그 내용을 한 수준 위로 이동하는 방법은 무엇입니까?

주어진 이름을 가진 디렉토리를 찾고 그 내용을 한 수준 위로 이동하는 방법은 무엇입니까?

나는 주어진 이름을 가진 모든 디렉토리를 찾는 방법을 알고 있습니다.

find . -name unnecessary_dir_level

파일을 상위 디렉터리로 이동하는 방법은 다음과 같습니다.

mv * ..

어떻게 결합하나요? - 예

find . -name unnecessary_dir_level -exec mv {}/* {}/.. \;

혼란을 일으키지 않고 이 작업을 완료하고 싶습니까? 아니면 어떻게 될까요? 나는 조언 없이 이것을 시도하고 싶지 않습니다(그리고 디렉토리가 너무 커서 합리적인 시간에 백업할 수 없습니다).

답변1

(계속 중단되지 않는) 옵션을 지원하는 구현을 사용하면 zsh다음을 수행할 수 있습니다.mv-n

for dir (**/unnecessary_dir_level(ND/od)) () {
  (( ! $# )) || mv -n -- $@ $dir:h/ && rmdir -- $dir
} $dir/*(ND)

어디:

  • for var (values) cmd루프의 짧은 버전입니다(프로그래밍 언어에서 더 일반적임) for.
  • **/: 전역 연산자, 즉모든 수준의 하위 디렉터리
  • Nglob 한정자: nullglob이 glob을 활성화합니다(일치하는 항목이 없어도 불평하지 마세요).
  • Dglob 한정자: dotglob이 glob을 활성화합니다(숨겨진 파일 포함).
  • /glob 한정자: 파일 형식으로 제한됨목차.
  • odglob 한정자: order by depth(해당 분기 이전에 나옴)
  • () { body; } args: 매개변수가 있는 익명 함수입니다.
  • 여기매개변수존재 $dir/*(ND): 숨김 파일을 포함한 모든 파일$dir
  • 이것이러한 파일(있는 경우)에 대해 실행한 다음 mv이제 비어 있어야 하는 rmdir파일에 대해 실행합니다 .$dir
  • $dir:h, (csh와 같은 디렉토리 이름) h.$dir

다음 mv * ..두 계정은 잘못되었습니다.

  • 옵션 구분 기호가 누락되었습니다.mv -- * ..
  • 숨겨진 파일이 누락되었습니다: mv -- *(D) ..zsh, ( (shopt -s nullglob failglob; exec mv -- * ..)in bash)
  • 또한: 상위 파일에 같은 이름의 파일이 있으면 데이터가 손실될 수 있습니다.
find . -name unnecessary_dir_level -exec mv {}/* {}/.. \;

{}/*glob이 호출되기 전에 쉘에 의해 확장되기 때문에 작동하지 않습니다 mv. 현재 디렉터리에 호출 디렉터리가 있으면 다른 디렉터리로 확장된 다음 {}잘못된 파일이 이동됩니다.


find다음 과 같이 bash비슷한 작업을 수행 할 수 있습니다 .

find . -depth -name unnecessary_dir_level -type d -exec \
  bash -O nullglob -O dotglob -c '
    for dir do
      set -- "$dir"/*
      (( ! $# )) || mv -n -- "$@" "${dir%/*}" && rmdir -- "$dir"
    done' bash {} +

답변2

버전 bash>= 4.0:

shopt -s globstar nullglob dotglob
for f in **/name/; do echo mv "$f"* "$f"..; done

출력이 괜찮아 보이면 삭제하세요 echo.

에서 man bash:

globstar: 설정된 경우 경로 이름 확장 컨텍스트에 사용된 패턴 **은 모든 파일과 0개 이상의 디렉터리 및 하위 디렉터리와 일치합니다. 패턴 뒤에 /가 오면 디렉터리와 하위 디렉터리만 일치합니다.

nullglob: 설정된 경우 bash는 파일 [...]과 일치하지 않는 패턴이 자체가 아닌 빈 문자열로 확장되도록 허용합니다.

dotglob: 설정된 경우 bash는 경로 이름 확장 결과에 "."로 시작하는 파일 이름을 포함합니다.

답변3

for loop를 사용하여 발견된 각 디렉터리의 내용을 이전 수준으로 이동할 수 있습니다 . 예를 들어, 내 디렉토리 temp에 파일이 있습니다 abc.

tmp/abc/
└── temp

다음 명령이 디렉토리 temp에 배치됩니다 tmp.

for i in ` find . -name abc ` ; do mv $i/* $i/.. ; done

관련 정보