سكريبت لترتيب الملفات و تنظيم الملفات

بسم الله و الحمد لله

هذا سكريبت كتبته لتنظيم ملفات مجلد التحميل و أيضا أي ملفات بالمنزل . شيء بسيط و عادي.

#!/usr/bin/env bash

#### التأكد من مسارات نقل الملفات

SOURCE=$(xdg-user-dir DOWNLOAD || echo $HOME/Downloads)


mkdir -p $SOURCE/{videos,audio,scripts,images,documents}


#### حذف المساحات البيضاء في أسماء الملفات .

while IFS= read -r -d '' i
  do
   
     case "$i" in
          *\ * )
              echo  mv "$i" $(echo $i | tr -s ' ,' '_')
             ;;
         *)
             echo "Nothing to do here"
            ;;
    esac
  
  done < <(find . -maxdepth 1 -not -path '*/.*' -not -name '.*' -prune -type f -print0)


#### نقل الملفات . أعتقد هذه الطريقة أفضل. توجد صيغ ناقصة. يمكن لكم أن تضيفوها.                                                        
    
     
while IFS= read -r -d '' f
 do
case "${f##*.}" in
  jpeg|jpg|png)  mv -vn "$f" $SOURCE/images ;;
  webm|mp4)  mv -vn "$f" $SOURCE/videos ;;
  mp3|m4a|opus)  mv -vn  "$f" $SOURCE/music ;;
  epub|pdf|txt|md)  mv -vn "$f" $SOURCE/documents ;;
  py|pl|sh|c)  mv -vn "$f" $SOURCE/scripts ;;
  *) echo "Do nothing" ;;
esac
done < <(find . -maxdepth 1 -not -path '*/.*' -prune -type f -print0)


#### نقل الملفات التي لا تحمل أي صيغة. اكتفيت بنوعين. هذا ما احتاجه شخصيا.

 while IFS= read -r -d '' f
do 
  if [[ $(file "$f") =~ ": Bourne-Again shell script" ]]; then
    mv -vn "$f" "$SOURCE/scripts"
  elif [[ $(file "$f") =~ ": ASCII text" ]]; then
    mv -vn "$f" "$SOURCE/documents"
  fi
done < <(find . -maxdepth 1 -not -path '*/.*' -not -name '.*' -prune -type f -print0)```
إعجاب واحد (1)

تقدر تجرب أمر xdg-user-dir عشان تسأله عن موقع مجلد التحميل, ﻷن ممكن اسم مجلد التحميل يكون مختلف عند مستخدم آخر. وإذا كان المستخدم ما منصب حزمة xdg-user-dirs فالكود يرجع لمجلد الافتراضي “~/Downloads”. ,وبأمكان نقل عدة ملفات الى مكان واحد بدل عدة أوامر لmv

#!/bin/bash

# lets create some dirs first

SOURCE=`xdg-user-dir DOWNLOAD || echo $HOME/Downloads`
mkdir -p $SOURCE/{videos,audio,scripts,archives,torrents,images,documents}

# remove any whitspace in file names. its a headache :) 
for i in * ; do mv "$i" $(echo $i | tr -s ' ,' '_') ; done

# a classic n00b way to move files :)

#move videos files
mv  *.mp4 *.mov *.webm $SOURCE/videos/ 2> /dev/null

#move doc files
mv *.pdf *.epub *.txt $SOURCE/documents/ 2> /dev/null

#move torrent files
mv *.torrent $SOURCE/torrents/ 2> /dev/null

#move script files
mv *.sh *.pl $SOURCE/scripts/ 2> /dev/null

#move archive files
mv *.tar.gz *.zip *.rar $SOURCE/archives/ 2> /dev/null

#move images files
mv *.png *.PNG *.jpg *.jpeg *.webp $SOURCE/images/ 2> /dev/null

# move files without extension based on their type
#script files
for f in * ; do file "$f" | grep 'script' ;if [ -f "$f" ] && [ $? == 0 ];then mv "$f" $SOURCE/scripts; else echo "the file is not a script";fi; done

#text files
for f in * ; do file "$f" | grep 'text' ;if [ -f "$f" ] && [ $? == 0 ];then mv "$f" $SOURCE/documents; else echo "the file is not a text file";fi; done

إعجابَين (2)

بارك الله فيك. هذه مراجعة لسكريبت . بناء على بعض الملاحظات .

#coding-utf8

# check if source directory exist.

[ -d $HOME/Downloads ]
if [ "$?" != 0 ]; then
    mkdir -p $HOME/Downloads
fi

SOURCE="/home/$USER/Downloads"

# lets create some dirs first

for p in $SOURCE/{videos,audio,scripts,archives,torrents,images,documents};do if [ -d "$p" ]; then printf '%s\n' "The directory: "$p" exist."; else mkdir -p "$p"; fi; done

# remove any whitspace in file names. its a headache :) 
for i in * ; do mv "$i" $(echo $i | tr -s ' ,' '_') ; done

# a classic n00b way to move files :)

#move videos files
mv  *.mp4 $SOURCE/videos/ 2> /dev/null
mv *.mov $SOURCE/videos/ 2> /dev/null
mv *.webm $SOURCE/videos/ 2> /dev/null

#move doc files
mv *.pdf $SOURCE/documents/ 2> /dev/null
mv *.epub $SOURCE/documents/ 2> /dev/null
mv *.txt $SOURCE/documents/ 2> /dev/null

#move torrent files
mv *.torrent $SOURCE/torrents/ 2> /dev/null

#move script files
mv *.sh $SOURCE/scripts/ 2> /dev/null
mv *.pl $SOURCE/scripts/ 2> /dev/null

#move archive files
mv *.tar.gz $SOURCE/archives/ 2> /dev/null

#move images files
mv *.png $SOURCE/images/ 2> /dev/null
mv *.PNG $SOURCE/images/ 2> /dev/null
mv *.jpg $SOURCE/images/ 2> /dev/null
mv *.jpeg $SOURCE/images/ 2> /dev/null

# move files without extension based on their type
#script files
for f in * ; do file "$f" | grep 'script' ;if [ -f "$f" ] && [ $? == 0 ];then mv "$f" i$SOURCE/scripts; else echo "the file is not a script";fi; done

#text files
for f in * ; do file "$f" | grep 'text' ;if [ -f "$f" ] && [ $? == 0 ];then mv "$f" $SOURCE/documents; else echo "the file is not a text file";fi; done

قمت باضافة امتحان لتأكد من وجود مجلد التحميلات . و أيضا استغلال المتغير SOURCE .

و أيضا طريقة أفضل لعمل المجلدات التي ستنقل لها الملفات. في حالة كانت موجودة. سيتم طباعة رسائل أخطاء. كما أشرت هذا عمل للاستخدام الشخصي. ليس شيء منظم و احترافي.

ربما لاحقا أضيف طرق أفضل. للجزء الأخير. أي نقل الملفات التي لا تحمل أي صيغة.

إعجابَين (2)
  1. الأفضل دائما أن تبدأ بسطر shebang، ويكون أول سطر في الملف وغير مسبوق بمسافة وفيه المسار المطلق للمفسر ومسبوقا بـ# ثم !. والمنصوح به في باش هو:

    #!/usr/bin/env bash
    
  2. لماذا تنفذ أمرا ثم تفحص حالته؟

    [ -d $HOME/Downloads ]
    if [ "$?" != 0 ]; then
    

    فيمكنك أن تكتب ‪if cmd; then‬ أو ‪if ! cmd; then‬، أي:

    if ! [ -d $HOME/Downloads ]; then
    
  3. لماذا تكرار مسار مجلد التنزيلات في ثلاثة أماكن؟ لقد عرّفت متغيرا فيه مساره، فاستخدمه في كل مرة إذًا ولا تكرره.

  4. صحيح أن ‪$HOME‬ هو نفسه ‪/home/$USER‬ في غالب الأحوال، لكن استخدام ‪$HOME‬ عموما أفضل.

  5. لماذا تسأل عن وجود المجلدات قبل إنشائها؟ ألست ستنفذ هذا البُريْمج كثيرا وليس مرة واحدة؟ فإما أن يكون وجودها خطأ فتوقف البريمج عندئذٍ (ولا تكتفي برسالة خطأ)، وإما أنه ليس بخطأ، فلا داعٍ أن تسأل أصلا. وفي هذه الحالة ‪mkdir -p‬ يكفيك لأنه لا يعطي خطأ إذا كان المجلد موجودا بالفعل.

  6. # remove any whitspace in file names. its a headache :)
    

    عليك أن تتعلم باش إذًا؛ لا مفر من ذلك. 😉 فليست المسافات وحدها المشكلة، بل أكثر الرموز الأخرى. ابحث عن ”quoting bash“. ولكن في ٩٠٪ من المواقف يكفيك أن تضع كل متغير بين علامتي تنصيص مزدوجتين، وأن تضع كل نص تكتبه بين علامتي تنصيص مفردتين إن كان فيه علامات غير الحروف والأرقام (أي المسافات والأقواس إلخ). ولكن طبعا لا تضع علامات الـglob (مثل النجمة) بين تنصيص وإلا لن تعمل.

  7. mv *.webm $SOURCE/videos/ 2> /dev/null
    

    لماذا تخبئ رسائل الأخطاء؟ أليست ضرورية؟ يجب أن يعلم المستخدم إذا تعذر نقل ملف بسبب تصادم الأسماء (وجود ملف آخر هناك بنفس الاسم) أو بسبب نقص المساحة (إن كان هذا المجلد على تقسيم آخر)، أو غير ذلك. وهي نادرة عموما، لكن عندما يحدث خطأ فإنك تريد أن تعلم أنه حدث ولماذا.

  8. for f in * ; do file "$f" | grep 'script' ;if [ -f "$f" ] && [ $? == 0 ];then mv "$f" i$SOURCE/scripts; else echo "the file is not a script";fi; done
    

    هذا سطر طويل جدا. لنقسمه إلى أسطر:

    for f in *; do
        file "$f" | grep 'script'
        if [ -f "$f" ] && [ $? == 0 ]; then
            mv "$f" i$SOURCE/scripts
        else
            echo "the file is not a script"
        fi
    done
    
    • لعلك لاحظت الآن حرف i الزائد في سطر نقل الملف. (دائما اجعل كودك مقروءًا؛ لنفسك وليس لغيرك. 😉)
    • رسالة «الملف ليس بُريمجا» لا تخبرني ما الملف المقصود مثلا، فلا أجدها مفيدة كثيرا. ولكن هل هذه الرسالة مطلوبة أصلا؟ المتوقع أن ملفات عديدة ليست بُريمجات، وليس في ذلك بأسا. فإذا كنت تريدها فعلى الأقل اذكر اسم الملف.
    • في هذا الكود تسأل عن نوع الملف أولا، ثم بعد ذلك تسأل عن وجوده وهل هو ملف أم لا. أليس العكس أفضل؟
    • الشيء المهم الذي أخّرتُه للنهاية: هذا الكود لن يعمل كما تريد أصلا! بل سينقل كل الملفات إلى مجلد البُريمجات. لأنك تنفذ أمرا (grep)، ثم تنفذ أمرا آخر (وهو ‪[ -f "$f" ]‬، وهو أمر في باش وليس مجرد بنية نحوية)، ثم تطلب حالة آخر أمر (وهو أمر التحقق الأخير، وليس أمر grep). فأنصحك أن تجرب دائما نسخا مصغرة من الأكواد إن شككت فيها.
    • وإذا عملت بهذه النقطة والنقطة رقم 2، فسيصير هذا الجزء كهذا:

      for f in *; do
          if [ -f "$f" ] && file "$f" | grep -q 'script'; then
              mv "$f" "$SOURCE/scripts"
          fi
      done
      
    • ولاحظ استخدام ‪-q‬ مع grep، فهذا يجعله لا يطبع أي ناتج، وإنما يَخرج بقيمة حالة مناسبة لاستخدامها مع if مباشرةً من غير وسيط أو مقارنة.
    • وجزء الملفات النصية التالي له مثله تماما.
  9. آخر شيء: لن يعمل هذا البُريمج إلا داخل مجلد التنزيلات. فرغم المتغير الذي في البداية وغير ذلك، إلا أن هذا البريمج يتعامل مع الملفات الموجودة في المجلد الحالي فقط. وأعرف حلين، أيسرهما هو الانتقال إلى مجلد التنزيلات، أي تنفيذ ‪cd "$SOURCE"‬، قبل التعامل مع أي ملفات.

3 إعجابات

أولا بارك الله فيك. جزاك الله خيرا على الملاحظات. مشاركة أطول من الموضوع ههههه
أعذرني. سأقوم بالتعقيب على البعض منها.رغم أنني مبتدأ . لست خبير و لا أي شيء.

كما أشرت في السابق . هنا
# a classic n00b way to move files :slight_smile:
أو هنا
** هذا عمل للاستخدام الشخصي. ليس شيء منظم و احترافي.**

لا توجد أي عبارة توحي أنني تعلمت الصدفة باش. و أنتهيت منها. أخذت دكتوراة.

بالنسبة لتعقيب. صراحة لا تحتاج الاشارة لها. هذا شيء واضح وضوح الشمس في السماء. كأنك تنصح شخص مسلم. أن يقول بسم الله قبل البدأ في الأكل.

  • الفحص مختصر و يعمل. الهدف منه التحقق من الحالة التي ينتهي بها فقط. لا أريد اضافة if statement .

  • تكرار المسارات. لا أعتقد موجودة في المشاركة الأخيرة. لا أعرف عن أي واحدة تتحدث.

  • اذا لم تسأل عن المجلدات قبل عملها سيعطي خطأ اذا كانت موجودة.

  • سطر حذف السماحات البيضاء. هذا ما أحتاجه فقط. أعرف أنه توجد طرق لحذف الرموز الأخرى. و حيل تجاوز المساحات البيضاء طويل.
    لا أن أدخل في النقاش فيه. ابحث stackoverflow . و أنظر عدد المشاركات حول المشكلة.

  • الذي لم تشير له. أن استخدام أداة find مع لاحقة exec و xargs أفضل في البحث و نقل الملفات. و أيضا اضافة خاصية لتحقق اذا كان هناك ملف بنفس الاسم. سيعطي رسالة خطأ. توجد أشاياء كثيرة . يحتاجها السكريبت. لم أقل أنه الأفضل. عندك نسخة أفضل لسكريبت كامل . شاركها بالمجتمع.

  • الجزء الأخير لنقل الملفات بدون صيغة. أعرف أنها ليست الطريقة الأفضل. ولكنني جربتها. و تعمل. توجد طريقة باستخدام awk أو أداة exiftool

و طريقة case esac أفضل في التعامل مع صيغ الملفات.

حرف i الزائد. رأيته بعد تسجيل الخروج من المجتمع. تركته لما بعد.

  • السكريبت سيعمل و لو كنت خارج مجلد التحميلات. عندك رسالة خطأ شاركها.

مثال لاستخدام أداة find. هذا فيما يتعلق بالملفات بدون صيغة .

find . -maxdepth 1 -type f -exec bash -c 'for f ; do file --mime-type "$f" ; done' bash '{}' +

  • هذا مسار يوجد به خليط من الملفات.
./Spacedrive-linux-x86_64.AppImage: application/x-executable
./README.md: text/plain
./set-hypr(1): text/x-shellscript
./pic: image/png
./config(1): application/json
./set-hypr: text/x-shellscript
./ghosts: text/x-shellscript
./style.css: text/plain
./auto-mover.sh: text/x-shellscript
./Sams_Journey.sid: application/octet-stream
./ytv-live: text/x-shellscript
./stopwatch.pl: text/x-perl
./bashrc(1): text/plain
./cava.sh: text/x-shellscript
./spkg: text/x-shellscript
./compton.conf: text/plain
./stopwatch1.pl: text/x-perl
./nix-tip: text/plain
./hyprStart: text/plain
./hyprland.conf: text/plain
./polybarstart: text/x-shellscript
./vimrc: text/plain
./char.lst: text/plain
./spv: text/x-shellscript
./lemonbar.sh: text/x-shellscript
./network-check: text/x-shellscript
./config: text/plain
./mover.sh: text/x-shellscript
./mpd.conf: text/plain
./screenshot: text/x-shellscript
./cpu.sh: text/x-shellscript
./Steel_Ranger.sid: application/octet-stream
./autoscript: text/x-shellscript
./key-switcher: text/x-shellscript
./Xresources: text/plain
./autoscriptmenu: text/x-shellscript
./documentss: text/x-shellscript
./polybar-config: text/plain
./targzdirs: text/x-shellscript
./bashrc: text/plain
./tarxzdirs: text/x-shellscript
./picom.conf: text/plain
./libssl.pc: text/plain
./automover: text/x-shellscript
./tpuTest: text/x-shellscript
./config.ini: text/plain
./prompt.sh: text/plain
./i3config: text/plain

find . -maxdepth 1 -type f -exec bash -c 'for f ; do file --mime-type "$f" | grep -Fq "shellscript" ;if [ "$?" == 0 ]; then echo mv -nv "$f" $SOURCE/scripts; fi;done' bash '{}' +

الطريقة لنقل الملفات.

mv -nv ./set-hypr(1) /scripts
mv -nv ./set-hypr /scripts
mv -nv ./ghosts /scripts
mv -nv ./auto-mover.sh /scripts
mv -nv ./ytv-live /scripts
mv -nv ./cava.sh /scripts
mv -nv ./spkg /scripts
mv -nv ./polybarstart /scripts
mv -nv ./spv /scripts
mv -nv ./lemonbar.sh /scripts
mv -nv ./network-check /scripts
mv -nv ./mover.sh /scripts
mv -nv ./screenshot /scripts
mv -nv ./cpu.sh /scripts
mv -nv ./autoscript /scripts
mv -nv ./key-switcher /scripts
mv -nv ./autoscriptmenu /scripts
mv -nv ./documentss /scripts
mv -nv ./targzdirs /scripts
mv -nv ./tarxzdirs /scripts
mv -nv ./automover /scripts
mv -nv ./tpuTest /scripts

تم اضافة لاحقة n- الى أداة mv .

يبدوا أن الموضوع سيطول. حقل تجارب . عندما أستقر على نسخة جيدة. سأغير المشاركة الأولى.

إعجاب واحد (1)

أولا بارك الله فيك. جزاك الله خيرا

جميعا. :blush:


لا توجد أي عبارة توحي أنني تعلمت الصدفة باش. و أنتهيت منها. أخذت دكتوراة.

إذًا لمَ نشرت هذا الموضوع؟ أليس لتتعلم؟ :wink:

فلو قلت عن كل شيء «لستُ خبيرا؛ أنا مجرد مبتدئ» فقد يثبطك ذلك عن التعلم.
ولو قلت «أنا خبير؛ أنا أعلم كل شيء» فهذه بداية الجهل!

لا تصف نفسك بأنك مبتدئ، وإنما ”fake it till you make it“ — وأنت تعلم بالفعل.

ولا تفكر في «الانتهاء من تعلم» أي شيء؛ فهذا يعني أنك ستتوقف، والذي يعني بداية التردي. إنما اسعَ دوما وتعلم. واستمر في التعلم حتى آخر أيامك.

فمثلا أنا اليوم، بعد عقد من الزمان من بدء تعلم باش، واستخدامها أغلب الأيام، وكتابة بُريمجات كثيرة بها بعضها يزيد على ألف سطر، احتجت للتأكد من بعض الأشياء أثناء كتابتي الرسالة السابقة.


الفحص مختصر و يعمل. الهدف منه التحقق من الحالة التي ينتهي بها فقط. لا أريد اضافة if statement .

لم أفهم؛ ما معنى «الفحص» مع قولك «لا أريد اضافة if statement»؟ وماذا تفعل if هنا إذًا؟

[ -d $HOME/Downloads ]
if [ "$?" != 0 ]; then
    mkdir -p $HOME/Downloads
fi

تكرار المسارات. لا أعتقد موجودة في المشاركة الأخيرة. لا أعرف عن أي واحدة تتحدث.

في مشاركتك الأخيرة، ثلاث مرات في الأسطر العشرة الأولى، تحديدا:

[ -d $HOME/Downloads ]
if [ "$?" != 0 ]; then
    mkdir -p $HOME/Downloads
fi

SOURCE="/home/$USER/Downloads"

مرتان ‪$HOME/Downloads‬ ومرة في تعريف SOURCE.


اذا لم تسأل عن المجلدات قبل عملها سيعطي خطأ اذا كانت موجودة.

هذا إذا استخدمت mkdir وحده، أما إذا استخدمت mkdir -p مثلما فعلت في كلتا المشاركتين، فلن يعطي خطأ. وانظر وصف ‪-p‬ في man mkdir.


سطر حذف السماحات البيضاء. هذا ما أحتاجه فقط. أعرف أنه توجد طرق لحذف الرموز الأخرى. و حيل تجاوز المساحات البيضاء طويل.

لا أعلم عنك. ولكن لدي الكثير من الملفات التي في أسمائها أقواس هلالية. (لعل أشهرها تنزيل ملف بنفس اسم ملف آخر، فيضيف المتصفح لاسم الجديد (1).) وهذه مثلها مثل المسافات.


لا أن أدخل في النقاش فيه. ابحث stackoverflow . و أنظر عدد المشاركات حول المشكلة.

لهذا ذكرت لك حل الـ«٩٠٪». :wink:


الذي لم تشير له. أن استخدام أداة find مع لاحقة exec و xargs أفضل في البحث و نقل الملفات.

صحيح. ولم أذكرها لسببين:

  1. تريد نقل الملفات الظاهرة التي في مجلد التنزيلات مباشرةً، وليست التي في أي مجلد فرعي. فاستخدام توسيع الصدفة (مثل * أو ‪*.mp4‬) أيسر في هذه الحالة من استخدام find . -maxdepth 1. وخصوصا أن find يحتاج أن يكون في صدر الأمر، فتكتبه أولا ثم تطلب من find نفسه تنفيذ ما تريد. أما أنماط التوسيع فمثلها مثل أسماء الملفات في الاستخدام؛ والتي لا تستخدم فيها إلا الصدفة العادية التي تعرفها.

  2. استخدام find متقدم أكثر من الصدفة المجردة، فليس من الحكمة أن يسألك سائل عن الماضي البسيط أو المضارع البسيط في الإنجليزية، فتشرح له الـsubjunctive. فـfind هو لغة وحده، ويحتاج طريقة مختلفة في التعامل، عكس الأنماط التي تستخدم مثل أسماء الملفات تماما.


و أيضا اضافة خاصية لتحقق اذا كان هناك ملف بنفس الاسم.

أردت أن أذكرها فعلا لكن نسيت. وما أردت أن أذكره تحديدا هو استخدام mv --interactive (أو mv -i اختصارا) ليسألك قبل تغطية أي ملف له نفس الاسم (وهذا اختياري في الغالب)، أو استخدام mv --no-clobber (أو mv -n اختصارا) والذي يرفض تغطية أي ملف بغير سؤال (ويوجد خيار لتغطية أي ملف بغير سؤال أيضا؛ انظر man mv). بل إني أري أن خيار ‪--interactive‬ ضروري جدا حتى أني أجعل أوامر mv وcp وrm في صدفتي تستخدمه دوما بغير أن أكتبه (بـalias).

(والأفضل دائما عند كتابة البُريمجات تفضيل الخيارات الطويلة على القصيرة، مثل ‪--interactive‬ بدلا من ‪-i‬.)


توجد أشاياء كثيرة . يحتاجها السكريبت.

صحيح. لكن هذه مهمتك! فأنت مستخدمه الأول.


لم أقل أنه الأفضل.

لا يوجد شيء اسمه «الأفضل» (بالألف واللام)! انظر إلى أي مشروع برمجي؛ نادر جدا أن تجد مشروعا يقول «لقد انتهينا؛ لا يوجد شيء يمكننا أن نحسّنه في هذا المشروع». نواة لينكس مثلا تصدر نسخة جديدة مستقرة كل ثلاثة أشهر. بل إن لغات البرمجة تصدر نسخا جديدة كل حين، حتى اللغات الأكثر جمودا مثل C، حتى Fortran، حتى COBOL!


عندك نسخة أفضل لسكريبت كامل . شاركها بالمجتمع.

«أفضل» في هذا السياق صفة «ذاتية» وليست «موضوعية». فالأفضل للبعض ليس الأفضل للكل.


الجزء الأخير لنقل الملفات بدون صيغة. أعرف أنها ليست الطريقة الأفضل. ولكنني جربتها. و تعمل. توجد طريقة باستخدام awk أو أداة exiftool

لم أقل أنها لن تعمل، ولم أتحدث عن الطريقة أصلا! ما قلته، بالنص، هو: «هذا الكود لن يعمل كما تريد أصلا! بل سينقل كل الملفات إلى مجلد البُريمجات». وذلك لأن شرط نقل الملفات هو ‪[ -f "$f" ] && [ $? == 0 ]‬، وهذا الشرط متحقق لجميع الملفات، بغض النظر عن ناتج grep السابق. وقد جربت نسخة مصغرة من هذا الكود أثناء كتابتي الرسالة السابقة، وجربت نسخة مصغرة أخرى أثناء كتابتي هذه الرسالة الآن؛ هذا الكود ينقل الملفات بالاعتماد على صدق الشرط ‪[ -f "$f" ]‬ وحده: أي أنه ينقل جميع الملفات بغض النظر عن نوع ما فيها.


و طريقة case esac أفضل في التعامل مع صيغ الملفات.

صحيح، فـcase أداة قوية جدا في باش لتنفيذ كود اعتمادا على مطابقته لنصوص أو أنماط.


حرف i الزائد. رأيته بعد تسجيل الخروج من المجتمع. تركته لما بعد.

وماذا لو لم تره إلا بعد تنفيذ الكود؟


السكريبت سيعمل و لو كنت خارج مجلد التحميلات. عندك رسالة خطأ شاركها.

ضع الأمر pwd قبل سطر إزالة المسافات. وربما تود أيضا أن تشغل البُريمج باستخدام bash -x وليس bash فقط، فهذا يعطيك تفصيلا للأوامر التي ينفذها فترى ماذا يفعل وما الملفات التي يعمل عليها.

لا ينقل هذا البُريمج الملفات إلا من المجلد الحالي. فإذا كنت في مجلد المنزل فسينقل ملفات مجلد المنزل إلى تلك المجلدات التي أنشأتها داخل مجلد التنزيلات.


مثال لاستخدام أداة find.

صحيح. وجميل أنك وصلت إليه. :smiley:


تم اضافة لاحقة n- الى أداة mv .

اختيار موفق. :+1:

إعجاب واحد (1)

عدنا :laughing: . الموضوع لم ينتهي بعد. أريد اضافة طريقة case esac . و أيضا تجنب طريقة

for f in $(...)

خبراء الصدفة شيل لا ينصحون بها :neutral_face:.
الطريقة الأفضل
while ...do...done

while IFS= read -r -d '' f
 do
case "${f##*.}" in
png) mv -nv "$f" $HOME/Downloads/images ;;
mp4)  mv -nv "$f" $HOME/Downloads/videos ;;
txt) mv -nv "$f" $HOME/Downloads/Documents ;;
*) echo "Do nothing" ;;
esac
done < <(find . -maxdepth 1 -not -path '*/.*' -type f -print0)

حيلة not -path- .لتجنب البحث في الملفات المخفية. ربما تسبب مشاكل تغيير أسماء ملفات الاعدادات. و لن تستطيع ولوج النظام. مثل ملف .xinitirc

لم أغير بعد المشاركة الأولى.

مثال تطبيقي للمشاركة الأخيرة

  • اضافة تحسينات على طريقة case esac .
#!/usr/bin/bash

while IFS= read -r -d '' f
 do
case "${f##*.}" in
  jpeg|jpg|png)  mv -vn "$f" $HOME/Downloads/images ;;
  webm|mp4)  mv -vn "$f" $HOME/Downloads/videos ;;
  mp3|m4a|opus)  mv -vn  "$f" $HOME/Downloads/music ;;
 epub|pdf|txt|md)  mv -vn "$f" $HOME/Downloads/documents ;;
py|pl|sh|c)  mv -vn "$f" $HOME/Downloads/scripts ;;
  *) echo "Do nothing" ;;
esac
done < <(find . -maxdepth 1 -not -path '*/.*' -type f -print0)

تصحيح أخطاء في الكتابة . اضافة صيغ مختلفة. لتجنب التكرار .

تم تعديل المشاركة الأولى. هذا يعني الموضوع انتهى. :smiley:

قمت باضافة لاحقة-prune لأداة البحث. أرى أنها مهمة اذا وضعت مباشرة بعد خاصية تحديد الاسم. و تعمل بشكل جيد. وجدتها عندما أقرأ هذا المقال. طبعا الرابط تعمق في تقاصيل. أغلب الاستخدمات العادية لا تتطرق لها.

  • -prune True; if the file is a directory, do not descend into it.
    If -depth is given, then -prune has no effect. Because
    -delete implies -depth, you cannot usefully use -prune and
    -delete together. For example, to skip the directory
    src/emacs and all files and directories under it, and
    print the names of the other files found, do something
    like this:
    find . -path ./src/emacs -prune -o -print