توی این درس یاد میگیری در درخت پوشههای لینوکس مثل یک نقشهخوان باتجربه حرکت کنی. با pwd میفهمی کجایی، با cd جابهجا میشوی، تفاوت مسیر مطلق (از / شروع میشود) و مسیر نسبی (از جایی که هستی) را میشناسی، علامتهای ~ (خانه)، . (همینجا) و .. (یک پوشه بالاتر) را به کار میبری، فایلهای مخفی را میبینی، خروجی ls -la و ls -lh را ستونبهستون میخوانی و با cd - بین دو پوشه میپری.
مسئله: «من الآن کجا هستم؟»
Section titled “مسئله: «من الآن کجا هستم؟»”در محیط گرافیکی همیشه پنجرهی پوشه را جلوی چشمت داری. در ترمینال هیچکدام نیست: فقط یک خط فرمان و یک «جای فعلی» نامرئی. اگر ندانی کجایی، دستور rm یا cp میتواند روی جای اشتباه اجرا شود. پس اولین مهارت لینوکس این است: همیشه بدانی کجایی و بتوانی به هر جایی بروی.
تشبیه: نشانی دادن در شهر
Section titled “تشبیه: نشانی دادن در شهر”نشانی مطلق مثل آدرس کامل پستی است: «تهران، خیابان آزادی، پلاک ۱۰». از هر کجا بخوانی همانجا میرسی. نشانی نسبی مثل «دو تا کوچه پایینتر، دست راست» است: فقط از جای فعلیات معنی دارد. اولی همیشه کار میکند ولی طولانی است؛ دومی کوتاه است ولی به جای فعلی بستگی دارد.
مثالهای عملی
Section titled “مثالهای عملی”برای تمرین حرکت، یک درخت کوچک میسازیم. (دستور mkdir -p که پوشهها را یکجا میسازد در درس بعد کامل میآید؛ فعلاً فقط اجرایش کن.)
mkdir -p projects/web/css projects/web/js projects/api/v1 docsecho "ساخته شد:"lsساخته شد:docsprojectsمثال ۱: من کجا هستم؟ pwd
Section titled “مثال ۱: من کجا هستم؟ pwd”pwd (print working directory) پوشهی کاری فعلی را چاپ میکند: همان «جای فعلی».
pwdecho "پوشهی خانهی من: $HOME"/home/aliپوشهی خانهی من: /home/aliهر پروسهی shell در هر لحظه فقط در یک پوشه است. pwd همیشه مسیر مطلق (کامل) را میدهد. ترمینالها معمولاً بیشتر مواقع (در پرامپت) هم همین را نشان میدهند (ali@pc:~/projects$).
مثال ۲: جابهجایی با cd
Section titled “مثال ۲: جابهجایی با cd”cd (change directory) پوشهی کاری را عوض میکند. بدون خروجی است؛ اگر موفق شود چیزی نمیگوید:
cd /var/logpwdcd /pwdcdpwd/var/log//home/aliسه نکته: ۱) cd /var/log با مسیر مطلق رفت. ۲) cd / به ریشه رفت. ۳) cd بدون argument به پوشهی خانه برمیگردد (کوتاهترین راه خانه رفتن).
مثال ۳: مسیر مطلق و نسبی
Section titled “مثال ۳: مسیر مطلق و نسبی”اگر مسیر با / شروع شود مطلق است؛ در غیر این صورت نسبی (نسبت به پوشهی فعلی):
cd /usrpwdcd share # نسبی: از /usr، پوشهی sharepwdcd /usr/share # مطلق: همان مقصدpwd/usr/usr/share/usr/share| نوع | شروع میشود با | مثال | به جای فعلی بستگی دارد؟ |
|---|---|---|---|
| مطلق | / |
/usr/share |
نه |
| نسبی | هر چیز دیگر | share، ../log |
بله |
| نسبت به خانه | ~ |
~/projects |
نه (از خانه) |
قاعدهی عملی: در دستورهای تایپی کوتاه از نسبی استفاده کن؛ در اسکریپتها و تنظیمات که از هر جایی ممکن است اجرا شوند، مطلق.
مثال ۴: ~ و . و ..
Section titled “مثال ۴: ~ و . و ..”سه علامت ویژهی مسیر:
| علامت | معنی |
|---|---|
~ |
پوشهی خانهی کاربر فعلی (/home/ali) |
. |
همین پوشهی فعلی |
.. |
یک پوشه بالاتر (والد) |
cd ~/projects/web/csspwdcd ..echo "بعد از cd .. → $(pwd)"cd ../..echo "بعد از cd ../.. → $(pwd)"cd ~/projects/web/csscd ../jsecho "به پوشهی همسطح (../js) → $(pwd)"cd ../../api/v1echo "از web/js به api/v1 (../../api/v1) → $(pwd)"/home/ali/projects/web/cssبعد از cd .. → /home/ali/projects/webبعد از cd ../.. → /home/aliبه پوشهی همسطح (../js) → /home/ali/projects/web/jsاز web/js به api/v1 (../../api/v1) → /home/ali/projects/api/v1.. را میشود پشت هم زنجیر کرد (../.. دو سطح بالا). و . بیشتر موقع اجرای برنامهی همین پوشه کاربرد دارد (./script.sh) و وقتی میخواهی بگویی «همینجا» (مثل cp file .).
اگر در /home/ali/projects/web/css هستی، با کدام دستور به /home/ali/projects/api میرسی؟
از css دو سطح بالا میروی (web، بعد projects) و بعد api.
مثال ۵: میانبر cd - و ~
Section titled “مثال ۵: میانبر cd - و ~”cd - به پوشهی قبلی برمیگردد (و مسیرش را چاپ میکند). برای جابهجایی بین دو جای دور از هم ایدهآل است:
cd /var/logcd ~echo "الان در: $(pwd)"cd -echo "بعد از cd - برگشتم به: $(pwd)"cd -echo "دوباره cd - → $(pwd)"الان در: /home/ali/var/logبعد از cd - برگشتم به: /var/log/home/aliدوباره cd - → /home/alishell پوشهی قبلی را در متغیر $OLDPWD نگه میدارد:
cd /etc; cd /usrecho "الان: $PWD | قبلی: $OLDPWD"الان: /usr | قبلی: /etcبنابراین cd - همان cd "$OLDPWD" است. این همان راهحل تمرین درس است: از /var/log به خانه بروی و برگردی فقط با دو دستور: cd و cd -.
مثال ۶: خواندن ls -l
Section titled “مثال ۶: خواندن ls -l”ls بهتنهایی فقط اسمها را میدهد. -l (long) اطلاعات کامل میدهد:
cd ~/projectsecho "hello" > web/index.txtls -lecho "--- در پوشهی web:"ls -l webtotal 8drwxr-xr-x 3 ali ali 4096 Oct 3 19:58 apidrwxr-xr-x 4 ali ali 4096 Oct 3 19:58 web--- در پوشهی web:total 12drwxr-xr-x 2 ali ali 4096 Oct 3 19:58 css-rw-r--r-- 1 ali ali 6 Oct 3 19:58 index.txtdrwxr-xr-x 2 ali ali 4096 Oct 3 19:58 jsهر خط چند ستون دارد (توضیح کامل دسترسیها در درس دسترسیها):
| ستون | مثال | معنی |
|---|---|---|
| ۱ | drwxr-xr-x |
نوع و دسترسی؛ d پوشه، - فایل، l لینک |
| ۲ | 4 |
تعداد لینکها (برای پوشهها: تعداد زیرپوشهها + ۲) |
| ۳ | ali |
مالک |
| ۴ | ali |
گروه |
| ۵ | 4096 |
حجم به بایت |
| ۶ | Oct 3 19:48 |
زمان آخرین تغییر |
| ۷ | api |
نام |
برای حجم خوانا از -h (human-readable) استفاده کن:
head -c 1500000 /dev/zero > big.binhead -c 3000 /dev/zero > mid.binls -l *.binecho "--- با -h:"ls -lh *.bin-rw-r--r-- 1 ali ali 1500000 Oct 3 19:58 big.bin-rw-r--r-- 1 ali ali 3000 Oct 3 19:58 mid.bin--- با -h:-rw-r--r-- 1 ali ali 1.5M Oct 3 19:58 big.bin-rw-r--r-- 1 ali ali 3.0K Oct 3 19:58 mid.binبهجای ۱۵۰۰۰۰۰ بایت، 1.5M میبینی. -lh همان -l -h است. و برای دیدن خود پوشه (نه محتوایش) از -d استفاده کن: ls -ld /var/log.
مثال ۷: فایلهای مخفی
Section titled “مثال ۷: فایلهای مخفی”فایل یا پوشهای که اسمش با . شروع شود مخفی است و ls معمولی نشانش نمیدهد (برای تنظیمات و فایلهای داخلی):
cd ~touch .secret-notelsecho "--- با -a (همه):"ls -aecho "--- با -A (همه بجز . و ..):"ls -Aecho "--- با -la (بلند و همه):"ls -la | head -8big.bindocsmid.binprojects--- با -a (همه):....bash_logout.bashrc.profile.secret-notebig.bindocsmid.binprojects--- با -A (همه بجز . و ..):.bash_logout.bashrc.profile.secret-notebig.bindocsmid.binprojects--- با -la (بلند و همه):total 1500drwxr-xr-x 4 ali ali 4096 Oct 3 19:58 .drwxr-xr-x 1 root root 4096 Oct 3 09:43 ..-rw-r--r-- 1 ali ali 220 Mar 31 2024 .bash_logout-rw-r--r-- 1 ali ali 3771 Mar 31 2024 .bashrc-rw-r--r-- 1 ali ali 807 Mar 31 2024 .profile-rw-r--r-- 1 ali ali 0 Oct 3 19:58 .secret-note-rw-r--r-- 1 ali ali 1500000 Oct 3 19:58 big.binbash: cd: /no/such/dir: No such file or directorybash: cd: /etc/hostname: Not a directorybash: cd: /root: Permission deniedدو ورودی ویژه همیشه هست: . (همین پوشه) و .. (والد). -A آنها را حذف میکند. فایلهای مخفی مهمی که میشناسی: .bashrc (تنظیمات shell)، .profile، .ssh/ (کلیدهای SSH در درسهای بعد).
مثال ۸: خطاهای رایج cd
Section titled “مثال ۸: خطاهای رایج cd”cd /no/such/dircd /etc/hostnamecd /rootسه پیام متفاوت: No such file or directory (مسیر وجود ندارد: غلط تایپی)، Not a directory (این یک فایل است نه پوشه) و Permission denied (وجود دارد ولی اجازهی ورود نداری). هر کدام راهحل جدا دارد.
مثال ۹: نام با فاصله و pushd/popd
Section titled “مثال ۹: نام با فاصله و pushd/popd”اگر اسم پوشه فاصله دارد، quote لازم است (درس shell):
mkdir "my project"cd "my project"pwdcd ..cd my\ projectpwd/home/ali/my project/home/ali/my projectبرای جابهجایی بین چند پوشه (نه فقط دو)، pushd و popd پشتهای از پوشهها نگه میدارند:
pushd /etc > /dev/nullpushd /var > /dev/nullpushd /usr > /dev/nullecho "پشته: $(dirs)"popd > /dev/null; echo "بعد از popd اول: $(pwd)"popd > /dev/null; echo "بعد از popd دوم: $(pwd)"پشته: /usr /var /etc ~بعد از popd اول: /varبعد از popd دوم: /etcپشت پرده: پوشهی کاری یک ویژگی پروسه است
Section titled “پشت پرده: پوشهی کاری یک ویژگی پروسه است”«پوشهی فعلی» چیزی نیست که روی دیسک نوشته شده باشد؛ هر پروسه (از جمله shell) در هسته یک فیلد به اسم cwd دارد. cd در shell همین فیلد را عوض میکند. میتوانی ببینی:
cd /var/logreadlink /proc/$$/cwdcd ~/projectsreadlink /proc/$$/cwd/var/log/home/ali/projects($$ شمارهی پروسهی shell است و /proc/$$/cwd یک لینک به پوشهی کاریاش.) و وقتی مسیر نسبی میدهی (cd share)، هسته آن را با cwd ترکیب میکند تا مسیر مطلق بسازد. به همین دلیل cd باید داخل خود shell اجرا شود (builtin)؛ اگر برنامهی جدا بود، فقط cwd فرزندش عوض میشد و بعد از تمام شدنش اثری نمیماند. و هر برنامهای که shell اجرا میکند cwd را از shell به ارث میبرد؛ برای همین ls بدون argument «پوشهی فعلی» را فهرست میکند.
جدولهای مرجع
Section titled “جدولهای مرجع”| دستور | کار |
|---|---|
pwd |
پوشهی کاری فعلی (مسیر مطلق) |
cd مسیر |
رفتن به مسیر (مطلق یا نسبی) |
cd یا cd ~ |
رفتن به پوشهی خانه |
cd .. |
یک سطح بالا |
cd - |
برگشت به پوشهی قبلی |
ls -l |
فهرست بلند (نوع، دسترسی، مالک، حجم، زمان) |
ls -a |
شامل فایلهای مخفی (با . و ..) |
ls -A |
شامل مخفیها بدون . و .. |
ls -h |
حجم خوانا (با -l) |
ls -d پوشه |
خودِ پوشه، نه محتوایش |
pushd / popd / dirs |
پشتهی پوشهها |
| متغیر | معنی |
|---|---|
$PWD |
پوشهی فعلی |
$OLDPWD |
پوشهی قبلی (برای cd -) |
$HOME |
پوشهی خانه |
اشتباهات رایج
Section titled “اشتباهات رایج”۱) تایپ غلط یا حروف بزرگ/کوچک
Section titled “۱) تایپ غلط یا حروف بزرگ/کوچک”cd /Etccd /etcpwd/etc/Etc با /etc فرق دارد (لینوکس به حروف کوچک/بزرگ حساس است). راهحل: با Tab کامل کن.
۲) فرض کردن اینکه cd چیزی چاپ میکند
Section titled “۲) فرض کردن اینکه cd چیزی چاپ میکند”cd وقتی موفق است ساکت است. برای اطمینان pwd بزن یا پرامپت را بخوان. راهحل: عادت کن بعد از جابهجاییهای مهم pwd بزنی.
۳) بدون quote برای اسم با فاصله
Section titled “۳) بدون quote برای اسم با فاصله”mkdir "my docs"cd my docsbash: cd: /Etc: No such file or directorybash: cd: too many argumentsbash: cd: /no/such/dir: No such file or directoryshell دو argument میبیند (my و docs) و cd فقط یکی میپذیرد: too many arguments. راهحل: cd "my docs".
۴) رفتن به پوشهای که وجود ندارد، بعد اجرای دستور خطرناک
Section titled “۴) رفتن به پوشهای که وجود ندارد، بعد اجرای دستور خطرناک”cd /no/such/dir && echo "این فقط وقتی اجرا میشود که cd موفق باشد"echo "کد خروج cd: $?"کد خروج cd: 1اگر cd شکست بخورد و دستور بعدی (مثلاً rm *) را مستقل بنویسی، روی پوشهی فعلی اجرا میشود (نه جایی که میخواستی). راهحل: cd پوشه && دستور تا فقط در صورت موفقیت اجرا شود.
۵) مسیر نسبی در اسکریپت
Section titled “۵) مسیر نسبی در اسکریپت”اسکریپتی که cd data مینویسد فقط وقتی کار میکند که از پوشهی درست اجرا شود. راهحل: در اسکریپتها از مسیر مطلق یا cd "$(dirname "$0")" استفاده کن (درسهای bash).
بدون هیچ آرگومانی cd بزن و نشان بده کجا هستی؛ بعد با cd - برگرد و نشان بده در کجایی.
دیدن جواب
cd /tmpcdpwdcd -pwd/home/ali/tmp/tmpتمرین اصلی: با کمترین تعداد دستور از /var/log به پوشهی خانه برو و برگرد. بعد در درخت درس، از ~/projects/web/css به ~/projects/api/v1 برو (فقط با مسیر نسبی) و ثابت کن در جای درستی هستی.
دیدن جواب
mkdir -p projects/web/css projects/api/v1cd /var/logcd # خانه (یک دستور)echo "خانه: $(pwd)"cd - # برگشت (دستور دوم)echo "برگشتم: $(pwd)"cd ~/projects/web/csscd ../../api/v1pwdخانه: /home/ali/var/logبرگشتم: /var/log/home/ali/projects/api/v1اولین بخش فقط دو دستور است (cd و cd -). برای بخش دوم از css دو سطح بالا (../..) میروی تا projects و بعد api/v1.
یک تابع up بنویس که یک عدد n بگیرد و n سطح بالا برود (up 3 مثل cd ../../..). با آن از عمیقترین پوشهی درس، تا ریشهی پروژه برگرد و نتیجه را چاپ کن.
دیدن جواب
mkdir -p a/b/c/dup() { local p=""; for i in $(seq 1 "$1"); do p="../$p"; done; cd "$p" || return; }cd a/b/c/decho "اینجا: $(pwd)"up 3echo "بعد از up 3: $(pwd)"اینجا: /home/ali/a/b/c/dبعد از up 3: /home/ali/aseq 1 3 عددهای ۱ تا ۳ را میدهد و حلقه سه بار ../ را به مسیر اضافه میکند.
آزمونک
Section titled “آزمونک”تفاوت مسیر مطلق و نسبی؟
مثلاً /usr/share مطلق و share نسبی است.
cd بدون argument چه میکند؟
معادل cd ~.
.. در مسیر یعنی…
. همین پوشه است و ~ خانه.
cd - چه میکند؟
از $OLDPWD استفاده میکند.
کدام دستور فایلهای مخفی را هم نشان میدهد؟
-A مخفیها را بدون . و .. نشان میدهد.
پیام «Not a directory» بعد از cd یعنی…
No such file: مسیر نیست؛ Permission denied: اجازه نداری.
جمعبندی
Section titled “جمعبندی”pwdجای فعلی را میگوید (مسیر مطلق)؛cdجابهجا میکند و در صورت موفقیت ساکت است.- مسیر مطلق از
/شروع میشود؛ نسبی از پوشهی فعلی.~خانه،.همینجا،..یک سطح بالا. cd(بدون argument) = خانه؛cd -= پوشهی قبلی؛pushd/popdبرای چند پوشه.ls -lستونهای نوع/دسترسی، مالک، گروه، حجم، زمان و نام دارد؛-hحجم خوانا،-aفایلهای مخفی.- پوشهی کاری ویژگی هر پروسه است؛
cdباید builtin باشد تا همان shell را عوض کند. - نام با فاصله را quote کن، و در اسکریپتها مسیر مطلق بنویس یا
cd پوشه && دستوررا به کار ببر.
| دستور | کاری که میکند |
|---|---|
pwd | پوشهی فعلی |
cd /var/log | رفتن با مسیر مطلق |
cd .. | یک سطح بالا |
cd | رفتن به خانه |
cd - | برگشت به پوشهی قبلی |
ls -la | فهرست بلند با فایلهای مخفی |
ls -lh | فهرست بلند با حجم خوانا |
ls -ld /var/log | خود پوشه (نه محتوا) |
pushd DIR / popd | پشتهی پوشهها |
echo $PWD $OLDPWD | پوشهی فعلی و قبلی |