일부 폴더에서 파일 그룹화


12

나는 같은 다른 확장자를 가진 일부 파일이 *.pdf, *.mp3, *.jpg그리고 몇 가지 다른 사람을. 그들 모두는 parent디렉토리에 저장됩니다 .

모든 확장명 목록을 가져오고이 확장명을 기반으로 폴더를 만든 다음 모든 파일을 관련 폴더로 옮기려면 어떻게해야합니까?

답변:


13

아래의 파이썬 스크립트가 작업을 수행합니다. 숨겨진 파일은 폴더와 확장자가없는 파일에 별도로 저장됩니다.

광범위한 목적으로 사용될 수 있으므로 몇 가지 옵션을 추가했습니다.

  • "재구성"에서 제외 할 확장을 설정할 수 있습니다. 단순히 모두 이동하려면 설정하십시오.exclude = ()
  • 빈 폴더로 수행 할 작업을 선택할 수 있습니다 ( remove_emptyfolders = True또는 False)
  • 파일을 이동 하는 대신 복사 하려는 경우 다음 줄을 바꾸십시오.
shutil.move(subject, new_dir+"/"+name)

으로:

shutil.copy(subject, new_dir+"/"+name) 

스크립트 :

#!/usr/bin/env python3

import os
import subprocess
import shutil

# --------------------------------------------------------
reorg_dir = "/path/to/directory_to_reorganize"
exclude = (".jpg") # for example
remove_emptyfolders = True
# ---------------------------------------------------------

for root, dirs, files in os.walk(reorg_dir):
    for name in files:
        subject = root+"/"+name
        if name.startswith("."):
            extension = ".hidden_files"
        elif not "." in name:
            extension = ".without_extension"
        else:
            extension = name[name.rfind("."):]
        if not extension in exclude:
            new_dir = reorg_dir+"/"+extension[1:]
            if not os.path.exists(new_dir):
                os.mkdir(new_dir)
            shutil.move(subject, new_dir+"/"+name)

def cleanup():
    filelist = []
    for root, dirs, files in os.walk(reorg_dir):
        for name in files:
            filelist.append(root+"/"+name)
    directories = [item[0] for item in os.walk(reorg_dir)]
    for dr in directories:
        matches = [item for item in filelist if dr in item]
        if len(matches) == 0:
            try:
                shutil.rmtree(dr)
            except FileNotFoundError:
                pass

if remove_emptyfolders == True:
    cleanup()

중복 파일을 원하지 않는 덮어 쓰기의 위험이있는 경우

몇 줄이 추가 될 경우 중복 가능성을 덮어 쓰는 것을 방지 할 수 있습니다. 아래 코드를 사용하면 중복 이름이 다음과 같이 바뀝니다.

duplicate_1_filename, duplicate_2_filename 

기타

스크립트 :

#!/usr/bin/env python3

import os
import subprocess
import shutil

# --------------------------------------------------------
reorg_dir = "/path/to/directory_to_reorganize"
exclude = (".jpg") # for example
remove_emptyfolders = True
# ---------------------------------------------------------

for root, dirs, files in os.walk(reorg_dir):
    for name in files:
        subject = root+"/"+name
        if name.startswith("."):
            extension = ".hidden_files"
        elif not "." in name:
            extension = ".without_extension"
        else:
            extension = name[name.rfind("."):]
        if not extension in exclude:
            new_dir = reorg_dir+"/"+extension[1:]
            if not os.path.exists(new_dir):
                os.mkdir(new_dir)
            n = 1; name_orig = name
            while os.path.exists(new_dir+"/"+name):
                name = "duplicate_"+str(n)+"_"+name_orig
                n = n+1
            newfile = new_dir+"/"+name
            shutil.move(subject, newfile)

def cleanup():
    filelist = []
    for root, dirs, files in os.walk(reorg_dir):
        for name in files:
            filelist.append(root+"/"+name)
    directories = [item[0] for item in os.walk(reorg_dir)]
    for dr in directories:
        matches = [item for item in filelist if dr in item]
        if len(matches) == 0:
            try:
                shutil.rmtree(dr)
            except FileNotFoundError:
                pass

if remove_emptyfolders == True:
    cleanup()

편집하다

OP를 염두에두고 사용 방법에 대한 지침을 추가하는 것을 잊었습니다. 중복 질문 (수 있으므로 및 수행 ) 표시, 그럼에도 불구하고 유용 할 수 있습니다.

사용하는 방법

  1. 스크립트 중 하나를 빈 파일로 복사하여 다음과 같이 저장하십시오. reorganize.py
  2. 스크립트의 헤드 섹션에서 대상 파일을 재구성 할 파일과 함께 설정하십시오.

    reorg_dir = "/path/to/directory_to_reorganize" 

    (디렉토리에 공백이 있으면 따옴표를 사용하십시오)

    제외하려는 확장 프로그램 (아마도 아래와 같이 없음) :

    exclude = ()

    나중에 빈 폴더를 제거하려면 다음을 수행하십시오.

    remove_emptyfolders = True
  3. 다음 명령으로 스크립트를 실행하십시오.

    python3 /path/to/reorganize.py

NB move 대신 파일 을 복사 하려면 다음을 바꾸십시오.

shutil.move(subject, new_dir+"/"+name)

으로:

shutil.copy(subject, new_dir+"/"+name)

작은 샘플로 먼저 시도하십시오.


12

find다소 복잡한 exec명령 과 함께 사용할 수 있습니다 .

find . -iname '*?.?*' -type f -exec bash -c 'EXT="${0##*.}"; mkdir -p "$PWD/${EXT}_dir"; cp --target-directory="$PWD/${EXT}_dir" "$0"' {} \;

# '*?.?*' requires at least one character before and after the '.', 
# so that files like .bashrc and blah. are avoided.
# EXT="${0##*.}" - get the extension
# mkdir -p $PWD/${EXT}_dir - make the folder, ignore if it exists

드라 이런 cp으로 교체하십시오 echo.


보다 효율적이고 깔끔한 것은 bash명령을 스크립트 에 저장하는 것입니다 (예 /path/to/the/script.sh: at ).

#! /bin/bash

for i
do
    EXT="${i##*.}" 
    mkdir -p "$PWD/${EXT}_dir"
    mv --target-directory="$PWD/${EXT}_dir" "$i" 
done

그런 다음 다음을 실행하십시오 find.

find . -iname '*?.?*' -type f -exec /path/to/the/script.sh {} +

이 방법은 매우 유연합니다. 예를 들어, 확장자 ( filename.ext) 대신 파일 이름을 사용 하려면 다음과 같이 사용합니다 EXT.

NAME="${i##*/}"
EXT="${NAME%.*}"

+1; 는 -iname '*.*'내가 대해 ... 좋은 생각이 걱정 된 코너 케이스의주의를 기울여야한다!
Rmano

하지 @Rmano *.fig.bak또는 .profile/.bashrc사람,하지만 그것은 단지 적어도 확장자를 가진 파일을 처리해야합니다. 감사.
muru

6
ls | gawk -F. 'NF>1 {f= $NF "-DIR"; system("mkdir -p " f ";mv " $0 " " f)}'

확장 목록 계산 (이동 후) :

ls -d *-DIR

확장 목록 계산하기 (이동 전) :

ls -X | grep -Po '(?<=\.)(\w+)$'| uniq -c | sort -n

(이 마지막 예에서, 우리는 각 확장에 대한 파일 수를 계산하고 정렬합니다)


1
죄송합니다 : 오타 "mkdir -f"가 "mkdir -p"로 수정되었습니다 (dir이 이미 존재하는 경우 무시)

정렬 후 적용되지 않아야합니까? 그리고 ls의 출력을 구문 분석하지 마십시오.
muru December

@muru, (1 부) ls -X는 확장이 정렬되도록 보장합니다. 최종 정렬은 확장 테이블을 발생 횟수-관련성별로 정렬하는 것입니다. (나는 맞습니까?).

@muru, (2 부) ls -X | grep -Po '(?<=\.)(\w+)$'는 정렬 된 확장 목록을 얻는 첫 번째 아이디어였습니다. 아주 나빠요? 당신은 무엇을 제안합니까?

나는 무엇을 잊었다 ls -X. 내가 권장하지 않는 이유 lsunix.stackexchange.com/q/128985/70524unix.stackexchange.com/q/112125/70524를 참조하십시오 . 당신이하는 일을 달성하기 위해 더 긴 길을 갈 것입니다 : find . -type f -name '*?.?*' -print0 | sed -z 's/.*\.//' | sort -zu( | uniq -cz카운트가 필요한 경우 선택 사항 ). 그리고 처음에는 (이것이 이식성find ... -print0 | gawk -v RS='\0'좋지않지만 ).
muru December

5

이 쉘 스크립트를 사용해보십시오.

#!/bin/sh
src=`dirname "$1"`/`basename "$1"`;
for file in "$src"/*?.?*; do
  if test -f "$file"; then
    dest="$src${file##*.}"_files;
    mkdir -p "$dest";
    mv "$file" "$dest";
  fi;
done;

# pass the directory to re-organize as first argument
# moves only regular files which have extension
# ignores other type of files including
# files having no extension, hidden files, directories, and links.

1
죄송합니다. 오류입니다. 발생할 때마다 교체에 내가해야 filepath와를 file. 직접 수정하겠습니다.
Prashant Karmakar

ls의 출력을 구문 분석하지 마십시오. 대신for file in "$src"/*?.?*; do ..
muru

일부 파일의 이름에 공백이 있으면 @muru가 올바르게 작동합니까?
Prashant Karmakar

@PrashantKarmakar 예, read예상치 못한 동작이있을 수 있습니다. 또한 mkdir 및 mv 명령에서 변수를 인용해야합니다.
muru

다음과 같은 경우 테스트 for i in *; do printf "%s\n" "$i"; done; for i in $(ls -d); do printf "%s\n" "$i"; done
해보십시오

2

Perl의 이름 바꾸기 / 이름 바꾸기가 설치되어있는 경우 :

rename 's!(.*)\.(\w+)$! mkdir($2); "$2/$&"!ge'  *
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.