เชลล์สคริปต์เพื่อสร้างไฟล์หากไม่มีอยู่?


20

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

#!/bin/bash

# Check for the file that gets created when the script successfully finishes.
if [! -f /Scripts/file.txt]
then
: # Do nothing. Go to the next step?
else
mkdir /Scripts # file.txt will come at the end of the script
fi

# Next command (macOS preference setting)
defaults write ...

ผลตอบแทนคือ

line 5: [!: command not found
mkdir: /Scripts: File exists

ไม่รู้จะทำยังไง ทุก ๆ ที่การค้นหาของ Google จะทำให้ฉันบ่งบอกถึงสิ่งที่แตกต่าง


6
ใส่รหัสของคุณในshellcheck.netและทบทวนคำแนะนำที่ได้รับ
roaima

12
เหตุผลใดที่คุณไม่สามารถเพียงแค่touchไฟล์และข้ามเงื่อนไข?
kirkpatt

คำตอบอื่น ๆ ด้านล่างแก้ไขข้อผิดพลาดทางไวยากรณ์ (ขาดช่องว่างระหว่าง[และ!) แต่อาจเป็นประโยชน์ที่จะชี้ให้เห็นที่นี่ซึ่ง[เป็นคำสั่งจริงใน Unix คำสั่ง Unix ต้องการพื้นที่ว่างบางส่วนระหว่างชื่อคำสั่งและข้อโต้แย้ง ใช่มันเป็น Bash builtinเหมือนกัน แต่ก็มีระบบเลขฐานสองอยู่/usr/bin/[ในระบบส่วนใหญ่
TheDudeAbides

คำตอบ:


44

วิธีแก้ปัญหาที่ง่ายกว่าอาจเป็นไปได้โดยไม่ต้องทำการทดสอบที่ชัดเจนเพียงใช้

mkdir -p /Scripts
touch /Scripts/file.txt

หากคุณไม่ต้องการให้เวลา "การเปลี่ยนแปลง" ของที่มีอยู่มีfile.txtการเปลี่ยนแปลงtouchคุณสามารถใช้touch -a /Scripts/file.txtเพื่อtouchเปลี่ยนเวลา "เข้าถึง" และ "เปลี่ยน" เท่านั้น


1
หากคุณไม่สนใจเกี่ยวกับ mtime >>/Scripts/file.txtคุณสามารถใช้ การดำเนินการนี้จะเปิดไฟล์เพื่อต่อท้ายและสร้างไฟล์หากไม่มีอยู่
kojiro

30

คุณได้รับข้อผิดพลาดเนื่องจากไม่มีที่ว่างระหว่าง[และ!อย่างไรก็ตามยังมีข้อบกพร่องบางอย่างในรหัสของคุณ ก่อนอื่นคุณต้องตรวจสอบว่าไม่มีไฟล์อยู่หรือไม่และถ้าไม่ได้ทำอะไร หากไฟล์มีอยู่คุณกำลังสร้างไดเร็กทอรี (แต่ไม่ได้ทำสิ่งใดเพื่อสร้างไฟล์)

นอกจากนี้คุณไม่จำเป็นต้องมีการดำเนินการใด ๆ คุณควรทำสิ่งต่อไปนี้

#! /bin/bash -
if [[ ! -e /Scripts/file.txt ]]; then
    mkdir -p /Scripts
    touch /Scripts/file.txt
fi

[command2]

นี่คือการตรวจสอบว่า/Scripts/file.txtไม่มีอยู่มันจะสร้าง/Scriptsไดเรกทอรีแล้วfile.txtไฟล์ คุณสามารถตรวจสอบการมีอยู่ของไดเรกทอรีแยกกันถ้าคุณต้องการ นอกจากนี้ฉันสังเกตเห็นว่าฉันใช้-eแทนที่-fคุณขอเพียงแค่ตรวจสอบการมีอยู่ของไฟล์ซึ่งเป็นสิ่งที่-eจะทำในกรณีที่-fตรวจสอบว่าเป็น "ไฟล์ปกติ" http://tldp.org/LDP/abs/html/fto HTML


ขอบคุณ @roaima ฉันได้อัปเดตคำตอบพร้อมคำแนะนำของคุณแล้ว
Jesse_b

ไฟล์นี้ไม่มีอยู่ แต่ไดเรคทอรีทำอะไร
Ant

3
@Ant: mkdir -p: สร้างไดเรกทอรีที่จำเป็นทั้งหมดโดยไม่บ่นหากมีอยู่แล้ว ตัวอย่าง: mkdir / home / user1 / tmp: จะสร้างลำดับชั้นนี้เป็นอิสระจากความเป็นจริงของ / home หรือ / home / user1 ไดเรกทอรีที่มีอยู่ก่อน แตะเพียงแค่จะอัปเดตเวลาของไฟล์ที่มีอยู่หรือสร้างใหม่หากไม่มีไฟล์อยู่ เราสามารถกำจัด if …แล้วส่วนหนึ่งเนื่องจากมันค่อนข้างโอเคที่จะเรียกใช้คำสั่ง 2 คำสั่งเหล่านั้นหากคุณต้องการให้แน่ใจว่ามีไดเรกทอรีเหล่านั้นอยู่และไฟล์นั้นอยู่ในนั้น
Olivier Dulac

ฉันเห็น! ขอบคุณสำหรับการชี้แจง :)
Ant

11

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

#!/bin/sh

ทุกระบบ Posix ต้องมีไฟล์นั้น ทุบตีเป็นตัวเลือกอย่างเคร่งครัด

ไม่จำเป็นต้องทดสอบว่ามีไดเรกทอรีอยู่หรือไม่

dir=/Scripts
mkdir -p $dir

หากต้องการสร้างไฟล์หากไม่มีอยู่

filename=$dir/file.txt
test -f $filename || touch $filename

หรือถ้าคุณต้องการ

filename=$dir/file.txt
if [ ! -f $filename ]
then
    touch $filename
fi

6

คุณมีข้อผิดพลาดทางไวยากรณ์ คุณจำเป็นต้องมีช่องว่างก่อนและหลังและ[]


3
#!/bin/bash

# Check for the file that gets created when the script successfully finishes.
CHECKFILE="/Scripts/file.txt"

CHECKDIR=$( dirname "$CHECKFILE" )

# The directory with the file must exist
mkdir -p "$CHECKDIR"
if [ ! -f "$CHECKFILE" ]; then
    # What to do if the file is not there
fi
touch "$CHECKFILE"

ด้านบนจะถือว่าไม่มี "กลอุบาย" เช่นการสร้างไดเรกทอรีที่เรียกว่า/Scripts/file.txt(ซึ่งอาจเป็นวิธีบังคับให้สคริปต์ป้อนรหัสสาขาหาก) หาก "file" เป็นไดเรกทอรีการทดสอบ -f จะล้มเหลวและคำสั่ง touch จะไม่เปลี่ยนแปลงอะไร


0

แนวทางของฉัน

#!/bin/sh

# input might contains spaces and other characters
FILEPATH="/tmp/some where/the file.blah"

# extract the file + dir names
FILE="`basename "${FILEPATH}"`"
DIR="`dirname "${FILEPATH}"`"

# create the dir, then the file
mkdir -p "${DIR}" && touch "${DIR}/${FILE}"

# show result
ls -l "$FILEPATH"

เอาท์พุต

  ./dofile.sh
  -rw-r--r-- 1 jmullee jmullee 0 Nov 15 21:23 /tmp/some where/the file.blah

.


1
คุณไม่ได้ตรวจสอบว่าไฟล์นั้นมีอยู่หรือไม่
PiedPiper

@piepdpiper เขาทำเช่นนี้นี่เป็นนัยในtouchและmkdir -p
xenoid

ides เดียวกันกับการตรวจสอบเพิ่มเติมดูเหมือนว่า: D = / boot / bork; F = fnord; mkdir -p "$ D" && {สัมผัส "$ D / $ F" && echo "สร้าง $ D / $ F ตกลง"; } || {echo "ไม่สามารถสร้าง dir '$ D'"; }
jmullee
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.