ฉันมีบางไฟล์ที่มีนามสกุลที่แตกต่างกันเช่น*.pdf
, *.mp3
, *.jpg
และอื่น ๆ น้อย พวกเขาทั้งหมดจะถูกเก็บไว้ในparent
ไดเรกทอรี
ฉันจะรับรายการส่วนขยายทั้งหมดสร้างโฟลเดอร์ตามส่วนขยายเหล่านี้แล้วย้ายไฟล์ทั้งหมดไปยังโฟลเดอร์ที่เกี่ยวข้องได้อย่างไร
ฉันมีบางไฟล์ที่มีนามสกุลที่แตกต่างกันเช่น*.pdf
, *.mp3
, *.jpg
และอื่น ๆ น้อย พวกเขาทั้งหมดจะถูกเก็บไว้ในparent
ไดเรกทอรี
ฉันจะรับรายการส่วนขยายทั้งหมดสร้างโฟลเดอร์ตามส่วนขยายเหล่านี้แล้วย้ายไฟล์ทั้งหมดไปยังโฟลเดอร์ที่เกี่ยวข้องได้อย่างไร
คำตอบ:
สคริปต์ python ด้านล่างทำงานได้ ไฟล์ที่ซ่อนจะถูกจัดเก็บแยกต่างหากในโฟลเดอร์รวมถึงไฟล์ที่ไม่มีนามสกุล
เนื่องจากอาจใช้สำหรับวัตถุประสงค์ที่กว้างขึ้นฉันจึงเพิ่มตัวเลือก:
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 ในใจเราทุกคนลืมที่จะเพิ่มคำแนะนำเกี่ยวกับวิธีการใช้ ตั้งแต่คำถามที่ซ้ำกันอาจจะ ( และไม่ ) ปรากฏขึ้นก็อาจจะมีประโยชน์ แต่อย่างไรก็ตาม
reorganize.py
ในส่วนหัวของสคริปต์ให้ตั้งค่าไดเรกทอรีเป้าหมาย (ด้วยไฟล์ที่จะจัดระเบียบใหม่):
reorg_dir = "/path/to/directory_to_reorganize"
(ใช้เครื่องหมายคำพูดหากไดเรกทอรีมีช่องว่าง)
ส่วนขยายที่เป็นไปได้ที่คุณต้องการยกเว้น (อาจไม่มีเช่นด้านล่าง):
exclude = ()
และหากคุณต้องการลบโฟลเดอร์ว่างในภายหลัง:
remove_emptyfolders = True
รันสคริปต์ด้วยคำสั่ง:
python3 /path/to/reorganize.py
หมายเหตุหากคุณต้องการคัดลอกไฟล์แทนที่จะย้ายให้แทนที่:
shutil.move(subject, new_dir+"/"+name)
โดย:
shutil.copy(subject, new_dir+"/"+name)
โปรดลองเป็นกลุ่มตัวอย่างก่อน
คุณสามารถใช้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
):
#! /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%.*}"
*.fig.bak
หรือ.profile/.bashrc
อันใดอันหนึ่ง แต่ควรจัดการกับไฟล์ที่มีนามสกุลอย่างน้อย ขอบคุณ
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
(ในตัวอย่างล่าสุดนี้เรากำลังคำนวณจำนวนไฟล์สำหรับแต่ละส่วนขยายและเรียงลำดับ)
ls -X | grep -Po '(?<=\.)(\w+)$'
เป็นความคิดแรกของฉันที่จะได้รับรายการส่วนขยายที่เรียงลำดับแล้ว มันแย่มากเหรอ? คุณแนะนำอะไร?
ls -X
ทำ ว่าทำไมฉันแนะนำต่อls
ให้ดูunix.stackexchange.com/q/128985/70524และunix.stackexchange.com/q/112125/70524 เพื่อให้บรรลุสิ่งที่คุณทำฉันจะไปอีกทาง: find . -type f -name '*?.?*' -print0 | sed -z 's/.*\.//' | sort -zu
(พร้อมตัวเลือก| uniq -cz
ถ้าจำเป็นต้องนับ) และfind ... -print0 | gawk -v RS='\0'
(แม้ว่าจะไม่ได้พกพาได้มาก ) สำหรับครั้งแรก
ลองเชลล์สคริปต์นี้
#!/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.
filepath
file
ฉันจะแก้ไขให้ถูกต้องโดยตรง
for file in "$src"/*?.?*; do ..
read
อาจมีพฤติกรรมที่ไม่คาดคิด คุณควรอ้างอิงตัวแปรในคำสั่ง mkdir และ mv
for i in *; do printf "%s\n" "$i"; done; for i in $(ls -d); do printf "%s\n" "$i"; done
หากคุณมีการติดตั้งเปลี่ยนชื่อ / prename ของ Perl:
rename 's!(.*)\.(\w+)$! mkdir($2); "$2/$&"!ge' *
-iname '*.*'
ควรดูแลกรณีมุมที่ผมเป็นห่วงเกี่ยวกับ ... ความคิดที่ดี!