ฉันจะตรวจสอบว่ามีไดเรกทอรีอยู่ในสคริปต์เชลล์ Bash ได้อย่างไร


3721

คำสั่งอะไรที่สามารถใช้ตรวจสอบว่ามีไดเรกทอรีอยู่หรือไม่ภายในสคริปต์เชลล์ Bash

คำตอบ:


5147

ในการตรวจสอบว่ามีไดเร็กทอรีอยู่ในเชลล์สคริปต์หรือไม่คุณสามารถใช้คำสั่งต่อไปนี้:

if [ -d "$DIRECTORY" ]; then
  # Control will enter here if $DIRECTORY exists.
fi

หรือเพื่อตรวจสอบว่าไม่มีไดเรกทอรีอยู่หรือไม่:

if [ ! -d "$DIRECTORY" ]; then
  # Control will enter here if $DIRECTORY doesn't exist.
fi

อย่างไรก็ตามตามที่Jon Ericsonระบุไว้คำสั่งที่ตามมาอาจไม่ทำงานตามที่ตั้งใจถ้าคุณไม่คำนึงว่าลิงก์สัญลักษณ์ไปยังไดเรกทอรีจะผ่านการตรวจสอบนี้เช่นกัน เช่นใช้สิ่งนี้:

ln -s "$ACTUAL_DIR" "$SYMLINK"
if [ -d "$SYMLINK" ]; then 
  rmdir "$SYMLINK" 
fi

จะสร้างข้อความแสดงข้อผิดพลาด:

rmdir: failed to remove `symlink': Not a directory

ดังนั้นลิงก์สัญลักษณ์อาจต้องได้รับการปฏิบัติแตกต่างกันหากคำสั่งในภายหลังคาดว่าจะมีไดเรกทอรี:

if [ -d "$LINK_OR_DIR" ]; then 
  if [ -L "$LINK_OR_DIR" ]; then
    # It is a symlink!
    # Symbolic link specific commands go here.
    rm "$LINK_OR_DIR"
  else
    # It's a directory!
    # Directory command goes here.
    rmdir "$LINK_OR_DIR"
  fi
fi

จดบันทึกเครื่องหมายคำพูดคู่ที่ใช้ห่อหุ้มตัวแปรโดยเฉพาะ เหตุผลนี้จะอธิบายโดย 8jean ในคำตอบอื่น

หากตัวแปรมีช่องว่างหรืออักขระผิดปกติอื่น ๆ อาจเป็นสาเหตุให้สคริปต์ล้มเหลว


29
หากคุณต้องการเล่นอย่างปลอดภัยด้วยเครื่องมือ GNU --ขอแนะนำให้ใช้ (เครื่องหมายสิ้นสุดของตัวเลือก) มิฉะนั้นหากตัวแปรของคุณมีบางอย่างที่ดูเหมือนตัวเลือกสคริปต์จะล้มเหลวเช่นเดียวกับการเว้นวรรค
Marc Mutz - mmutz

2
สำหรับรุ่นที่ทันสมัยของ bash, ksh, ฯลฯ [... ] เป็น builtin
fpmurphy

79
สิ่งหนึ่งที่ต้องเก็บไว้ในใจ: [ ! -d "$DIRECTORY" ]จะเป็นจริง แต่อย่างใดถ้า$DIRECTORYไม่ได้อยู่หรือถ้าไม่อยู่ แต่ไม่ได้เป็นไดเรกทอรี พิจารณาสิ่งที่ชอบif [ ! -d "$DIRECTORY" ] ; then mkdir "$DIRECTORY" ; fi; สิ่งนี้จะล้มเหลวหาก"$DIRECTORY"เป็นไฟล์ (แน่นอนคุณควรตรวจสอบว่าmkdirสำเร็จหรือไม่มีหลายสาเหตุที่ทำให้ล้มเหลว)
Keith Thompson

5
มันอาจจะมีมูลค่าการกล่าวขวัญว่าทันทีที่ตรวจสอบได้ดำเนินการสถานการณ์สามารถเปลี่ยนแปลงได้เนื่องจากกระบวนการอื่น ๆ ในหลายกรณีจะเป็นการดีกว่าที่จะสร้างหรือใช้ไดเรกทอรีและตอบสนองต่อความล้มเหลว
Alfe

12
แทนการทดสอบสำหรับทั้งไดเรกทอรี ( -d) และ symlink ( -L) if [ -d "${THING:+$THING/}" ]ก็ง่ายเพียงแค่ต่อท้ายเฉือนกับตัวแปรเช่น ไดเรกทอรีจะไม่รังเกียจเครื่องหมายทับ ไฟล์จะประเมินเป็นเท็จ Empty จะยังคงว่างเปล่าดังนั้น false และ symlink จะได้รับการแก้ไขไปยังปลายทาง แน่นอนมันขึ้นอยู่กับเป้าหมายของคุณ ถ้าคุณอยากไปที่นั่นก็โอเค หากคุณต้องการที่จะลบมันแล้วรหัสในคำตอบนี้จะดีกว่า
ghoti

530

อย่าลืมล้อมตัวแปรด้วยเครื่องหมายคำพูดคู่เสมอเมื่ออ้างอิงถึงมันในสคริปต์ Bash เด็กวันนี้เติบโตขึ้นมาด้วยความคิดที่ว่าพวกเขาสามารถมีช่องว่างและตัวละครตลกอื่น ๆ อีกมากมายในชื่อไดเรกทอรีของพวกเขา (Spaces! ย้อนกลับไปในสมัยของเราพวกเราไม่มีช่องว่างแฟนซี!;)

อยู่มาวันหนึ่งเด็กคนหนึ่งจะเรียกใช้สคริปต์ของคุณด้วยการ$DIRECTORYตั้งค่า"My M0viez"และสคริปต์ของคุณจะระเบิด คุณไม่ต้องการที่ ดังนั้นใช้สิ่งนี้

if [ -d "$DIRECTORY" ]; then
    # Will enter here if $DIRECTORY exists, even if it contains spaces
fi

9
อีกเหตุผลที่ควรใช้เครื่องหมายคำพูดคู่ในกรณีที่ไม่ได้ตั้งค่า $ DIRECTORY ด้วยเหตุผลบางประการ
Jon Ericson

2
"ล้อมตัวแปรในเครื่องหมายคำพูดคู่เสมอ ... ในสคริปต์ทุบตี" สำหรับทุบตีเทคนิคไม่จำเป็นเมื่อใช้ [[... ]]; ดูtldp.org/LDP/abs/html/testconstructs.html#DBLBRACKETS (หมายเหตุ: ไม่มีการแยกคำ): "ไม่มีการขยายชื่อไฟล์หรือการแยกคำที่เกิดขึ้นระหว่าง [[และ]] แต่มีการขยายพารามิเตอร์และการแทนที่คำสั่ง"
ไมเคิล

2
ไดเร็กทอรีบน Unix / Linux ไม่ควรมีช่องว่างใด ๆ และไม่ควรปรับใช้สคริปต์ในภายหลัง มันไม่ดีพอที่ Windows จะรองรับมันด้วยผลที่ตามมาทั้งหมดจากการเขียนสคริปต์ของ Windows แต่โปรดสำหรับความรักในสิ่งที่ไม่จำเป็นต้องแนะนำข้อกำหนดที่ไม่จำเป็น
tvCa

18
@tvCa ฉันพบว่าผู้ใช้โดยทั่วไปต้องการได้รับอนุญาตให้มีความยืดหยุ่นมากขึ้นในชื่อไดเรกทอรีแทนที่จะถูกบังคับให้ทำสิ่งต่าง ๆ ได้ง่ายขึ้นสำหรับนักพัฒนา (ในความเป็นจริงเมื่อต้องรับมือกับชื่อไฟล์นานผมหาคนโดยไม่มีช่องว่างที่จะมีอาการปวดเป็นที่ฆ่าตัดคำแม้ว่าตัวผมเองได้รับความเดือดร้อนในอดีตที่ผ่านมาจากการไม่ได้คิดเป็นเส้นทางที่มีช่องว่างในสคริปต์และโปรแกรม.)
JAB

2
ฮ้า ช่องว่างเป็นเพียงตัวละครที่ไม่มีร่ายมนตร์ปกติ อย่างไรก็ตามคุณสามารถหลบหนีด้วยแบ็กสแลช
uchuugaka

228

หมายเหตุการทดสอบ-dสามารถสร้างผลลัพธ์ที่น่าประหลาดใจ:

$ ln -s tmp/ t
$ if [ -d t ]; then rmdir t; fi
rmdir: directory "t": Path component not a directory

ไฟล์ภายใต้: "เมื่อใดไดเรกทอรีจะไม่ใช่ไดเรกทอรี" คำตอบ: "เมื่อ symlink ไปยังไดเรกทอรี" การทดสอบอย่างละเอียดมากขึ้นเล็กน้อย:

if [ -d t ]; then 
   if [ -L t ]; then 
      rm t
   else 
      rmdir t
   fi
fi

ท่านสามารถหาข้อมูลเพิ่มเติมในคู่มือการทุบตีในการแสดงออกเงื่อนไขทุบตีและ[คำสั่ง builtinและcommmand[[ สารประกอบ


12
หรือสมมติว่ามันเป็นเพียงสิ่งที่จำเป็นในการทำงานในไดเรกทอรี (และการเชื่อมโยงสามารถละเลย) => if [ -d tmpdir -a ! -L tmpdir ]; then echo "is directory"; rmdir tmpdir; fi... หรือสำหรับคำสั่งหนึ่งที่สามารถทำงานได้ทั้งการเชื่อมโยงและ dirs:rm -r tmpdir
ไมเคิล

218

ผมหาคู่วงเล็บรุ่นtestทำให้การเขียนการทดสอบตรรกะเป็นธรรมชาติมากขึ้น:

if [[ -d "${DIRECTORY}" && ! -L "${DIRECTORY}" ]] ; then
    echo "It's a bona-fide directory"
fi

สำหรับif [[ -d "$TARFILE" ]]ฉัน [[: ไม่พบ
TheVillageIdiot

15
@TheVillageIdiot และ @Hedgehog คุณใช้ bash shell หรือไม่ เครื่องหมายวงเล็บคู่ไม่รองรับในระดับสากล นี่คือคำตอบ SO ในจุดนั้น: stackoverflow.com/questions/669452/…
yukondude

6
และใน Busybox เถ้ามีตัวเลือกสะสมค่าเริ่มต้น[[ ]]ได้รับการสนับสนุน [ ]แต่ไม่ได้ในความเป็นจริงให้การทำงานที่แตกต่างกันไป หากการพกพาเป็นเรื่องที่น่ากังวลให้[ ]ใช้วิธีแก้ไขปัญหาที่จำเป็น
dubiousjim

6
... ถ้าใช้โครงสร้างทุบตีในสคริปต์เปลือกบรรทัดแรกของสคริปต์ควรจะ: # / bin / ทุบตี (และไม่ # / bin / SH, ksh ฯลฯ !)!
ไมเคิล

เมื่อใช้วงเล็บเหลี่ยมสองชั้นในทุบตีคุณไม่จำเป็นต้องพูดตัวแปร
Hubert Grzeskowiak

157

แบบฟอร์มสั้น:

[ -d "$DIR" ] && echo "Yes"

6
การทำงานนี้เช่นนี้ if $dir is a dir, then echo "yes"? บิตของคำอธิบายที่จะช่วยให้ :)
Martijn

5
cmd && otherชวเลขเป็นเรื่องธรรมดาสำหรับif cmd; then other; fi- งานนี้กับภาษาโปรแกรมส่วนใหญ่ที่สนับสนุนตรรกะบูลีนและเป็นที่รู้จักกันประเมินผลการลัดวงจร
tripleee

1
พฤติกรรมไม่เหมือนกันภายใต้set -e(ซึ่งเป็นแนวปฏิบัติที่ดีที่สุดในการโปรแกรมเชลล์ )
dolmen

1
@dolmen [ -d "$DIR" ]มีการตรวจสอบ (ตามด้วย&& echo Yes) ดังนั้นฉันเชื่อว่าset -eไม่มีความแตกต่างกับพฤติกรรมของสคริปต์ (เช่นหากการทดสอบล้มเหลวสคริปต์จะดำเนินการตามปกติ)
tzot

132

ในการตรวจสอบว่ามีไดเรกทอรีอยู่หรือไม่คุณสามารถใช้ifโครงสร้างแบบง่าย ๆดังนี้

if [ -d directory/path to a directory ] ; then
# Things to do

else #if needed #also: elif [new condition]
# Things to do
fi

คุณยังสามารถทำได้ในเชิงลบ:

if [ ! -d directory/path to a directory ] ; then
# Things to do when not an existing directory

หมายเหตุ : ระวัง เว้นช่องว่างไว้ที่ด้านใดด้านหนึ่งของทั้งเปิดและปิดวงเล็บปีกกา

ด้วยไวยากรณ์เดียวกันคุณสามารถใช้:

-e: any kind of archive

-f: file

-h: symbolic link

-r: readable file

-w: writable file

-x: executable file

-s: file size greater than zero

นี่เป็นวิธีที่ดีกว่าคำตอบที่ได้รับการยอมรับในปี 2008 นอกเหนือจากการออกนอกหัวข้อด้วยการสลับไฟล์?
Dan Dascalescu

ดีกว่าเพราะ [! ไดเรกทอรี -d / เส้นทางไปยังไดเรกทอรี]
user1855805

108
  1. สคริปต์ง่าย ๆ เพื่อทดสอบว่ามีไดเรกทอรีหรือไฟล์อยู่หรือไม่:

    if [ -d /home/ram/dir ]   # For file "if [-f /home/rama/file]"
    then
        echo "dir present"
    else
        echo "dir not present"
    fi
  2. สคริปต์ง่าย ๆ เพื่อตรวจสอบว่ามีไดเรกทอรีอยู่หรือไม่:

    mkdir tempdir   # If you want to check file use touch instead of mkdir
    ret=$?
    if [ "$ret" == "0" ]
    then
        echo "dir present"
    else
        echo "dir not present"
    fi

    สคริปต์ด้านบนจะตรวจสอบว่ามีไดเรกทอรีอยู่หรือไม่

    $? ถ้าคำสั่งสุดท้ายคือความสำเร็จมันจะส่งกลับ "0" มิฉะนั้นค่าที่ไม่เป็นศูนย์ สมมติว่าtempdirมีอยู่แล้ว จากนั้นmkdir tempdirจะให้ข้อผิดพลาดดังนี้:

    mkdir: ไม่สามารถสร้างไดเรกทอรี 'tempdir': มีไฟล์อยู่


4
อันที่สองจะสร้างไดเรกทอรีหากไม่มีอยู่ในตอนแรก งั้นมันก็ไม่ใช่ idempotent
Shihe Zhang

👆👆👆 อันที่สองดูอันตราย เนื่องจากมันสร้างไดเรคทอรีจึงไม่เป็นความจริงอีกต่อไปที่ dir จะไม่ปรากฏ
Chris

92

คุณสามารถใช้test -d(ดูman test)

-d file เป็นจริงถ้ามีไฟล์อยู่และเป็นไดเรกทอรี

ตัวอย่างเช่น:

test -d "/etc" && echo Exists || echo Does not exist

หมายเหตุ: testคำสั่งเหมือนกับนิพจน์เงื่อนไข[(ดู:) man [ดังนั้นจึงสามารถพกพาข้ามเชลล์สคริปต์ได้

[- นี่คือคำพ้องความหมายสำหรับtestbuiltin แต่อาร์กิวเมนต์สุดท้ายต้องเป็นตัวอักษรเพื่อให้ตรงกับการเปิด][

สำหรับตัวเลือกที่เป็นไปได้หรือความช่วยเหลือเพิ่มเติมให้ตรวจสอบ:

  • help [
  • help test
  • man test หรือ man [

55

หรือสำหรับบางสิ่งที่ไร้ประโยชน์อย่างสมบูรณ์:

[ -d . ] || echo "No"

6
มันจะไม่พิมพ์ "ไม่" ไดเรกทอรีปัจจุบันมีอยู่เสมอเว้นแต่จะลบโดยเธรดอื่นหรือวิธีอื่น
Jahid

ตัวอย่างที่สมบูรณ์แบบ :) ระบุว่าวิธีการ "ที่ไม่ซ้ำกัน" จะมีคำตอบบางอย่างเมื่อเทียบกับคำตอบที่ได้รับการยอมรับ
Sergey จส

4
เหตุใดจึงมีการอัปโหลดหลายครั้งมากเกินไป ไม่ตอบคำถาม
codeforester

เพราะมันเป็นคำตอบที่ดีที่สุด EVA
คาร์ลมอร์ริสัน

52

นี่คือสำนวนที่ใช้งานได้จริงมาก:

(cd $dir) || return # Is this a directory,
                    # and do we have access?

ฉันมักจะห่อมันในฟังก์ชั่น:

can_use_as_dir() {
    (cd ${1:?pathname expected}) || return
}

หรือ:

assert_dir_access() {
    (cd ${1:?pathname expected}) || exit
}

สิ่งที่ดีเกี่ยวกับวิธีนี้คือฉันไม่ต้องคิดถึงข้อความแสดงข้อผิดพลาดที่ดี

cdจะให้ข้อความมาตรฐานหนึ่งบรรทัดถึงข้อผิดพลาดมาตรฐานแล้ว มันจะให้ข้อมูลมากกว่าที่ฉันจะสามารถให้ได้ โดยทำการแสดงcdภายใน subshell( ... )คำสั่งจะไม่ส่งผลกระทบต่อไดเรกทอรีปัจจุบันของผู้โทร ถ้ามีไดเรกทอรีอยู่, subshell นี้และฟังก์ชั่นเป็นเพียงแค่ไม่มี

ถัดไปเป็นข้อโต้แย้งที่ว่าเราส่งผ่านไปยัง:cd ${1:?pathname expected}นี่เป็นรูปแบบที่ซับซ้อนยิ่งขึ้นของการทดแทนพารามิเตอร์ซึ่งจะอธิบายในรายละเอียดเพิ่มเติมด้านล่าง

Tl; dr: ถ้าสตริงที่ส่งผ่านไปยังฟังก์ชั่นนี้ว่างเปล่าเราจะออกจาก subshell อีกครั้ง( ... )และกลับมาจากฟังก์ชั่นด้วยข้อความแสดงข้อผิดพลาดที่กำหนด


ข้อความจากksh93หน้าคน:

${parameter:?word}

หาก parameter มีการตั้งค่าและไม่เป็นโมฆะให้แทนที่ค่าของมัน มิฉะนั้นให้พิมพ์wordและออกจากเชลล์ (หากไม่ใช่แบบโต้ตอบ) หากwordไม่ได้ระบุไว้ข้อความมาตรฐานจะถูกพิมพ์

และ

หากไม่ได้ระบุเครื่องหมายจุดคู่:จากการแสดงออกด้านบนเชลล์จะตรวจสอบเฉพาะพารามิเตอร์ที่ตั้งค่าไว้หรือไม่

การใช้ถ้อยคำที่นี่เป็นเรื่องแปลกสำหรับเอกสารเชลล์ซึ่งwordอาจอ้างอิงถึงสตริงที่สมเหตุสมผลรวมถึงช่องว่าง

ในกรณีพิเศษนี้ฉันรู้ว่าข้อความแสดงข้อผิดพลาดมาตรฐาน1: parameter not setไม่เพียงพอดังนั้นฉันจึงซูมเข้ากับประเภทของค่าที่เราคาดหวังที่นี่ - pathnameของไดเรกทอรี

บันทึกปรัชญา:

เปลือกไม่ได้เป็นภาษาเชิงวัตถุดังนั้นข้อความบอกว่าไม่pathname directoryในระดับนี้ฉันต้องการให้มันง่าย - ข้อโต้แย้งของฟังก์ชั่นเป็นเพียงสตริง


สิ่งนี้ทำมากกว่าแค่การตรวจสอบสิ่งที่มีอยู่: การตรวจสอบนี้สำหรับการเข้าถึงในระดับผู้ใช้ ดังนั้นคำถามจึงมีอยู่เพื่อการดำรงอยู่เท่านั้น ดังนั้นคำตอบที่ถูกต้องคือtest -d@Grundlefleck อธิบาย
F. Hauri

7
@ F.Hauri - เขาไม่ได้ขออะไรอีกแล้วนั่นเป็นเรื่องจริง อย่างไรก็ตามฉันพบว่าปกติฉันต้องรู้มากกว่านั้น
Henk Langeveld

และไม่เคยเกิดขึ้นกับฉันเลยที่การทดสอบจะไม่สามารถสรุปได้เว้นแต่ว่ามันจะเป็นรูต test -d /unreadable/existsจะล้มเหลวแม้ว่าข้อโต้แย้งจะมีอยู่
Henk Langeveld

36
if [ -d "$Directory" -a -w "$Directory" ]
then
    #Statements
fi

รหัสข้างต้นจะตรวจสอบว่ามีไดเรกทอรีอยู่หรือไม่และสามารถเขียนได้หรือไม่


1
-a นั้นเหมือนกันกับ -e มีการ "เลิกใช้แล้ว" และการใช้งานไม่ได้รับการสนับสนุน
CousinCocaine

27
DIRECTORY=/tmp

if [ -d "$DIRECTORY" ]; then
    echo "Exists"
fi

ลองออนไลน์


จำspaceหลังจากที่[-> [ `` ฉันได้รับข้อผิดพลาดเนื่องจากไม่มีที่ว่าง
Raj

4
อีกครั้งคำตอบนี้ได้รับแล้วในปี 2008 พร้อมคำอธิบายที่เป็นประโยชน์มากขึ้น สิ่งใหม่เฉพาะที่นี่คือสนามเด็กเล่นออนไลน์
Dan Dascalescu


21

คุณสมบัติเพิ่มเติมโดยใช้ find

  • ตรวจสอบการมีอยู่ของโฟลเดอร์ภายในไดเรกทอรีย่อย:

    found=`find -type d -name "myDirectory"`
    if [ -n "$found"]
    then
        # The variable 'found' contains the full path where "myDirectory" is.
        # It may contain several lines if there are several folders named "myDirectory".
    fi
  • ตรวจสอบการมีอยู่ของหนึ่งหรือหลายโฟลเดอร์ตามรูปแบบภายในไดเรกทอรีปัจจุบัน:

    found=`find -maxdepth 1 -type d -name "my*"`
    if [ -n "$found"]
    then
        # The variable 'found' contains the full path where folders "my*" have been found.
    fi
  • ทั้งสองอย่างรวมกัน ในตัวอย่างต่อไปนี้จะตรวจสอบการมีอยู่ของโฟลเดอร์ในไดเรกทอรีปัจจุบัน:

    found=`find -maxdepth 1 -type d -name "myDirectory"`
    if [ -n "$found"]
    then
        # The variable 'found' is not empty => "myDirectory"` exists.
    fi

สวัสดีนีแอล find -maxdepth 1 -type d -name 'pattern'ความคิดของคุณอาจจะเป็นประโยชน์ในการตรวจสอบการดำรงอยู่ของไดเรกทอรีขึ้นอยู่กับรูปแบบเช่นนี้: คุณรังเกียจไหมถ้าฉันต่อท้ายคำตอบนี้ Cheers;)
olibre

20

ที่จริงแล้วคุณควรใช้เครื่องมือหลายอย่างเพื่อให้ได้วิธีกันกระสุน:

DIR_PATH=`readlink -f "${the_stuff_you_test}"` # Get rid of symlinks and get abs path
if [[ -d "${DIR_PATH}" ]] ; Then # Now you're testing
    echo "It's a dir";
fi

ไม่มีความจำเป็นใด ๆ "${}"ที่จะต้องกังวลเกี่ยวกับช่องว่างและอักขระพิเศษตราบใดที่คุณใช้

โปรดทราบว่า[[]]ไม่สามารถพกพาได้[]แต่เนื่องจากคนส่วนใหญ่ทำงานกับรุ่นที่ทันสมัยของ Bash (เพราะหลังจากนั้นคนส่วนใหญ่ไม่ได้ทำงานกับ command line :-p) ประโยชน์จึงยิ่งใหญ่กว่าปัญหา


17

คุณเคยคิดที่จะทำในสิ่งที่คุณอยากทำifแทนที่จะมองข้ามหรือไม่?

คือถ้าคุณต้องการตรวจสอบการมีอยู่ของไดเรกทอรีก่อนที่คุณจะเข้าไปลองทำสิ่งนี้:

if pushd /path/you/want/to/enter; then
    # Commands you want to run in this directory
    popd
fi

หากเส้นทางที่คุณให้pushdมีอยู่คุณจะต้องป้อนและมันจะออกด้วย0ซึ่งหมายความว่าthenส่วนของคำสั่งจะดำเนินการ หากไม่มีอยู่จะไม่มีสิ่งใดเกิดขึ้น (นอกเหนือจากเอาต์พุตบางตัวที่บอกว่าไม่มีไดเรกทอรีซึ่งอาจเป็นผลข้างเคียงที่เป็นประโยชน์สำหรับการแก้ไขข้อบกพร่อง)

ดูเหมือนดีกว่านี้ซึ่งต้องทำซ้ำตัวเอง:

if [ -d /path/you/want/to/enter ]; then
    pushd /path/you/want/to/enter
    # Commands you want to run in this directory
    popd
fi

สิ่งเดียวกันที่ทำงานร่วมกับcd, mv, rmฯลฯ ... ถ้าคุณลองพวกเขาในไฟล์ที่ไม่อยู่พวกเขาจะออกจากที่มีข้อผิดพลาดและพิมพ์ข้อความบอกว่ามันไม่ได้อยู่ของคุณและthenบล็อกจะถูกข้ามไป หากคุณลองพวกเขาในไฟล์ที่มีอยู่คำสั่งจะดำเนินการและออกด้วยสถานะของการ0อนุญาตให้thenบล็อกของคุณเพื่อดำเนินการ


2
pushd คือวิธีที่สง่างามที่สุดในการทำสิ่งนี้สำหรับฉัน ผมกำลังจะโพสต์เป็นคำตอบ :)
melMass

15

ในการตรวจสอบมากกว่าหนึ่งไดเรกทอรีให้ใช้รหัสนี้:

if [ -d "$DIRECTORY1" ] && [ -d "$DIRECTORY2" ] then
    # Things to do
fi

คุณจะตรวจสอบว่ามันไม่มีอยู่ได้อย่างไร
perrohunter


15
[[ -d "$DIR" && ! -L "$DIR" ]] && echo "It's a directory and not a symbolic link"

หมายเหตุ: การอ้างอิงตัวแปรเป็นแนวปฏิบัติที่ดี

คำอธิบาย:

  • -d: ตรวจสอบว่าเป็นไดเรกทอรีหรือไม่
  • -L: ตรวจสอบว่าเป็นลิงก์สัญลักษณ์หรือไม่

คำอธิบายจะเป็นไปตามลำดับ (โดยการแก้ไขคำตอบของคุณไม่ใช่ที่นี่ในความคิดเห็น)
Peter Mortensen


11

คำตอบนี้รวมเป็นสคริปต์เชลล์

ตัวอย่าง

$ is_dir ~                           
YES

$ is_dir /tmp                        
YES

$ is_dir ~/bin                       
YES

$ mkdir '/tmp/test me'

$ is_dir '/tmp/test me'
YES

$ is_dir /asdf/asdf                  
NO

# Example of calling it in another script
DIR=~/mydata
if [ $(is_dir $DIR) == "NO" ]
then
  echo "Folder doesnt exist: $DIR";
  exit;
fi

is_dir

function show_help()
{
  IT=$(CAT <<EOF

  usage: DIR
  output: YES or NO, depending on whether or not the directory exists.

  )
  echo "$IT"
  exit
}

if [ "$1" == "help" ]
then
  show_help
fi
if [ -z "$1" ]
then
  show_help
fi

DIR=$1
if [ -d $DIR ]; then 
   echo "YES";
   exit;
fi
echo "NO";

10

การใช้การ-eตรวจสอบจะตรวจสอบไฟล์และสิ่งนี้รวมถึงไดเรกทอรี

if [ -e ${FILE_PATH_AND_NAME} ]
then
    echo "The file or directory exists."
fi

1
และตอบคำถามของ OP ไม่ถูกต้อง - เป็นไดเรกทอรีหรือไม่
Mark Stewart

8

ตามความคิดเห็นของโจนาธาน :

หากคุณต้องการสร้างไดเรกทอรีและยังไม่มีอยู่เทคนิคที่ง่ายที่สุดคือการใช้mkdir -pซึ่งสร้างไดเรกทอรี - และไดเรกทอรีที่ขาดหายไปตามเส้นทาง - และไม่ล้มเหลวหากมีไดเรกทอรีอยู่แล้วเพื่อให้คุณสามารถทำมันได้ทั้งหมด ในครั้งเดียวกับ:

mkdir -p /some/directory/you/want/to/exist || exit 1

7
if [ -d "$DIRECTORY" ]; then
    # Will enter here if $DIRECTORY exists
fi

นี่ไม่เป็นความจริงอย่างสมบูรณ์ ...

หากคุณต้องการไปยังไดเรกทอรีนั้นคุณต้องมีสิทธิ์ดำเนินการในไดเรกทอรีด้วย บางทีคุณอาจจำเป็นต้องมีสิทธิ์ในการเขียนเช่นกัน

ดังนั้น:

if [ -d "$DIRECTORY" ] && [ -x "$DIRECTORY" ] ; then
    # ... to go to that directory (even if DIRECTORY is a link)
    cd $DIRECTORY
    pwd
fi

if [ -d "$DIRECTORY" ] && [ -w "$DIRECTORY" ] ; then
    # ... to go to that directory and write something there (even if DIRECTORY is a link)
    cd $DIRECTORY
    touch foobar
fi

7

ใช้fileโปรแกรม เมื่อพิจารณาถึงไดเรกทอรีทั้งหมดเป็นไฟล์ใน Linux การออกคำสั่งต่อไปนี้น่าจะพอเพียง:

file $directory_name

กำลังตรวจสอบไฟล์ที่ไม่มีอยู่: file blah

เอาท์พุท: cannot open 'blah' (No such file or directory)

การตรวจสอบไดเรกทอรีที่มีอยู่: file bluh

เอาท์พุท: bluh: directory


1
ความคิดที่ดี แต่ไม่ดีในทั้งสองกรณีคำสั่ง file จะส่งคืนรหัสออก 0 เสมอ นอกจากนี้เมื่อไม่สามารถหาไฟล์ / ไดเรกทอรี :(.
อันตราย 89

6

lsคำสั่งร่วมกับ-l (ยาวรายการ) ผลตอบแทนที่ตัวเลือกคุณลักษณะข้อมูลเกี่ยวกับไฟล์และไดเรกทอรี
โดยเฉพาะอย่างยิ่งตัวอักษรแรกของการls -lส่งออกมันมักจะเป็นdหรือ-(เส้นประ) ในกรณีของdรายการที่ระบุไว้เป็นไดเรกทอรีแน่นอน

คำสั่งต่อไปนี้ในหนึ่งบรรทัดจะบอกคุณว่าISDIRตัวแปรที่กำหนดมีเส้นทางไปยังไดเรกทอรีหรือไม่:

[[ $(ls -ld "$ISDIR" | cut -c1) == 'd' ]] &&
    echo "YES, $ISDIR is a directory." || 
    echo "Sorry, $ISDIR is not a directory"

การใช้งานจริง:

    [claudio@nowhere ~]$ ISDIR="$HOME/Music" 
    [claudio@nowhere ~]$ ls -ld "$ISDIR"
    drwxr-xr-x. 2 claudio claudio 4096 Aug 23 00:02 /home/claudio/Music
    [claudio@nowhere ~]$ [[ $(ls -ld "$ISDIR" | cut -c1) == 'd' ]] && 
        echo "YES, $ISDIR is a directory." ||
        echo "Sorry, $ISDIR is not a directory"
    YES, /home/claudio/Music is a directory.

    [claudio@nowhere ~]$ touch "empty file.txt"
    [claudio@nowhere ~]$ ISDIR="$HOME/empty file.txt" 
    [claudio@nowhere ~]$ [[ $(ls -ld "$ISDIR" | cut -c1) == 'd' ]] && 
        echo "YES, $ISDIR is a directory." || 
        echo "Sorry, $ISDIR is not a directoy"
    Sorry, /home/claudio/empty file.txt is not a directory

+1 แต่เมื่อ ISDIR ไม่มีอยู่คุณจะได้รับข้อความแสดงข้อผิดพลาดและข้อความวินิจฉัยของคุณ
ysap


5

หากคุณต้องการตรวจสอบว่ามีไดเรกทอรีอยู่หรือไม่ไม่ว่าจะเป็นไดเรกทอรีจริงหรือ symlink ให้ใช้สิ่งนี้:

ls $DIR
if [ $? != 0 ]; then
        echo "Directory $DIR already exists!"
        exit 1;
fi
echo "Directory $DIR does not exist..."

คำอธิบาย: คำสั่ง "ls" ให้ข้อผิดพลาด "ls: / x: ไม่มีไฟล์หรือไดเรกทอรีดังกล่าว" หากไม่มีไดเรกทอรีหรือ symlink และตั้งค่ารหัสส่งคืนซึ่งคุณสามารถเรียกคืนผ่าน "$?" เพื่อไม่ใช่ - ว่าง (ปกติ "1") ตรวจสอบให้แน่ใจว่าคุณตรวจสอบรหัสส่งคืนโดยตรงหลังจากเรียก "ls"


3
หรือคุณสามารถใช้เวอร์ชันที่สั้นกว่านี้:if ! ls $DIR 2>/dev/null; then echo "$DIR does not exist!"; fi
derFunk

5

(1)

[ -d Piyush_Drv1 ] && echo ""Exists"" || echo "Not Exists"

(2)

[ `find . -type d -name Piyush_Drv1 -print | wc -l` -eq 1 ] && echo Exists || echo "Not Exists"

(3)

[[ -d run_dir  && ! -L run_dir ]] && echo Exists || echo "Not Exists"

หากพบปัญหาด้วยหนึ่งในวิธีการที่ให้ไว้ข้างต้น:

ด้วยlsคำสั่ง; กรณีที่ไม่มีไดเรกทอรี - ข้อความแสดงข้อผิดพลาดจะปรากฏขึ้น

[[ `ls -ld SAMPLE_DIR| grep ^d | wc -l` -eq 1 ]] && echo exists || not exists

-ksh: ไม่: ไม่พบ [ไม่มีไฟล์หรือไดเรกทอรีดังกล่าว]


"เหนือ" หมายถึงอะไร? สามบรรทัดคำสั่งในคำตอบนี้หรือคำตอบก่อนหน้า? (โปรดตอบกลับโดยแก้ไขคำตอบของคุณไม่ใช่ที่นี่ในความคิดเห็นขอบคุณล่วงหน้า)
Peter Mortensen

4

มีทางออกที่ดีออกมี แต่ท้ายที่สุดทุกสคริปต์จะล้มเหลวหากคุณไม่ได้อยู่ในไดเรกทอรีที่ถูกต้อง ดังนั้นรหัสเช่นนี้:

if [ -d "$LINK_OR_DIR" ]; then
if [ -L "$LINK_OR_DIR" ]; then
    # It is a symlink!
    # Symbolic link specific commands go here
    rm "$LINK_OR_DIR"
else
    # It's a directory!
    # Directory command goes here
    rmdir "$LINK_OR_DIR"
fi
fi

จะดำเนินการได้สำเร็จหากในขณะที่คุณอยู่ในไดเรกทอรีที่มีไดเรกทอรีย่อยที่คุณตรวจสอบ

ฉันเข้าใจคำถามเริ่มต้นเช่นนี้เพื่อตรวจสอบว่าไดเรกทอรีมีอยู่โดยไม่คำนึงถึงตำแหน่งของผู้ใช้ในระบบไฟล์หรือไม่ ดังนั้นการใช้คำสั่ง 'ค้นหา' อาจทำเคล็ดลับ:

dir=" "
echo "Input directory name to search for:"
read dir
find $HOME -name $dir -type d

วิธีการแก้ปัญหานี้ดีเพราะช่วยให้การใช้สัญลักษณ์แทนซึ่งเป็นคุณสมบัติที่มีประโยชน์เมื่อค้นหาไฟล์ / ไดเรกทอรี ปัญหาเพียงอย่างเดียวคือถ้าไม่มีไดเร็กทอรีการค้นหาคำสั่ง 'find' จะพิมพ์อะไรไปยังเอาต์พุตมาตรฐาน (ไม่ใช่โซลูชันที่สวยงามสำหรับรสนิยมของฉัน) และจะไม่มีทางออกศูนย์ บางทีอาจมีคนปรับปรุงเรื่องนี้


13
ฉันจะโกรธเคืองถ้าโปรแกรมตรวจดูทั้งฮาร์ดไดรฟ์ของฉันเพื่อค้นหาไดเรกทอรีแทนที่จะมองอย่างสุภาพในไดเรกทอรีการทำงานปัจจุบันของฉันหรือใช้เส้นทางที่แน่นอนที่ฉันให้ไว้ สิ่งที่คุณแนะนำอาจจะดีสำหรับเครื่องมือที่มีชื่อlocateแต่ไม่ดีสำหรับสิ่งอื่น ...
sarnold
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.