INPUT_FILE=`ls -rt $MY_DIR/FILE.*.xml | head -1 | xargs basename`
ฉันต้องการรันคำสั่งที่สอง ( head -1
) เฉพาะเมื่อคำสั่งแรกสำเร็จ ฉันจะปรับปรุงคำสั่งนี้ได้อย่างไร
INPUT_FILE=`ls -rt $MY_DIR/FILE.*.xml | head -1 | xargs basename`
ฉันต้องการรันคำสั่งที่สอง ( head -1
) เฉพาะเมื่อคำสั่งแรกสำเร็จ ฉันจะปรับปรุงคำสั่งนี้ได้อย่างไร
คำตอบ:
ลองสิ่งนี้:
INPUT_FILE=`ls -rt "$MY_DIR"/FILE.*.xml | head -1 | xargs -r basename`
การผ่านxargs
การ-r
ตั้งค่าสถานะจะทำให้การทำงานนั้นต่อbasename
เมื่ออ่านอย่างน้อยหนึ่งรายการจากอินพุตมาตรฐาน ( head -1
)
head -1
จะทำงาน แต่คุณจะไม่เห็นหรือบันทึกผลลัพธ์ใด ๆ จากมัน
นอกจากนี้ถ้าคุณไม่ต้องการให้ผู้ใช้เพื่อดูออกข้อผิดพลาดใด ๆ จากls
คุณสามารถเปลี่ยนเส้นทางls
ของกระแส stderr /dev/null
ไป
INPUT_FILE=`ls -rt "$MY_DIR"/FILE.*.xml 2> /dev/null | head -1 | xargs -r basename`
$MY_DIR
นอกจากนี้ทราบว่าผมเพิ่มอัญประกาศรอบ ด้วยวิธีนี้คำสั่งจะไม่ล้มเหลวหาก$MY_DIR
มีช่องว่าง
หากคุณกำลังใช้เปลือกที่ทันสมัยเช่นทุบตีคุณควรใช้$( )
เปลือกจับแทนการตีกลับ คุณควรพิจารณาเปลี่ยนสไตล์ของตัวแปรของคุณ โดยทั่วไปคุณควรหลีกเลี่ยงการใช้ชื่อตัวแปรตัวพิมพ์ใหญ่ทั้งหมดในสคริปต์ สไตล์นั้นสงวนไว้สำหรับตัวแปรสงวนและตัวแปรด้านสิ่งแวดล้อม
input_file=$(ls -rt "$my_dir"/FILE.*.xml 2> /dev/null | head -1 | xargs -r basename)
ls -rt GLOB 2>/dev/null | head -n1 | xargs -r basename
ผล
ในไพพ์ไลน์คำสั่งทั้งหมดจะเริ่มต้นและรันพร้อมกันไม่ใช่หนึ่งคำสั่งหลังจากนั้น ดังนั้นคุณต้องเก็บเอาท์พุทที่ไหนสักแห่ง
if ls_output=$(ls -rtd -- "$MY_DIR"/FILE.*.xml); then
first_file=$(printf '%s\n' "$ls_output" | head -n 1)
first_file_name=$(basename -- "$first_file")
fi
โปรดทราบว่ามันถือว่าชื่อไฟล์ไม่มีอักขระขึ้นบรรทัดใหม่ การใช้xargs
ยังหมายถึงปัญหาเกี่ยวกับอักขระว่างเปล่าเครื่องหมายอัญประกาศเดี่ยวและแบ็กสแลช การปล่อยตัวแปรที่ไม่ได้กล่าวถึงจะหมายถึงปัญหาเกี่ยวกับช่องว่างแท็บและอักขระตัวแทน ลืมจะหมายถึงมีปัญหากับชื่อไฟล์ที่เริ่มต้นด้วย--
-
ในการรับ basename ของไฟล์ที่เก่าที่สุดzsh
โดยไม่มีข้อ จำกัด ใด ๆ ในตัวอักขระ (หลีกเลี่ยงปัญหาเรื่องขนาดของอาร์กิวเมนต์ที่ จำกัด ไปยังคำสั่ง):
first_file_name=($MY_DIR/FILE.*.xml(Om[1]:t))
หากไม่มีการจับคู่คำสั่งนั้นจะล้มเหลวและยกเลิกสคริปต์ คุณยังสามารถทำสิ่งต่อไปนี้
first_file_name=($MY_DIR/FILE.*.xml(NOm[1]:t))
ในกรณีนี้first_file_name
อาร์เรย์จะมี 1 องค์ประกอบหากมีการจับคู่หรือ 0 ถ้าไม่ จากนั้นคุณสามารถทำได้:
if (($#first_file_name)); then
printf 'Match: %s\n' $first_file_name
else
echo >&2 No match
fi
ค้นหาไฟล์ที่แก้ไขล่าสุดในไดเรกทอรี:
latest() {
local file path=${1:-.} ext=${2-} latest
for file in "${path%/}"/*"$ext"; do
[[ $file -nt $latest ]] && latest=$file
done
[[ $latest ]] && printf '%s\n' "$latest"
}
การใช้งาน: latest [directory/path/ [.extension]]
แทนที่จะเรียกbasename
ใช้ให้ใช้การขยายพารามิเตอร์
in_file=$(latest in/my/dir .xml)
base_fn=${in_file##*/} base_fn=${base_fn%.*}
ในไดเรกทอรีที่มีเนื้อหาเหล่านี้:
foo.xml bar.xml baz.xml newest.xml
เนื้อหาของตัวแปร base_fn จะเป็น: newest
หากต้องการใช้สิ่งนี้อย่างถูกต้องเพื่อตอบสนองวัตถุประสงค์ของคำขอของคุณ:
check_dir=/path/to/check
check_ext=.xml
if in_file=$(latest "$check_dir" "$check_ext"); then
base_fn=${in_file##*/} base_fn=${base_fn%.*}
else
printf '%s\n' "No file found in $check_dir" >&2
fi
แก้ไข: เมื่อตรวจสอบคำถามฉันได้ตระหนักว่าls
คำสั่งในคำถามกำลังมองหาไฟล์ที่เก่าที่สุดในไดเรกทอรี ฟังก์ชั่นเดียวกันนี้สามารถเปลี่ยนชื่อเป็นoldest
และมี[[ $file -ot $oldest ]] && oldest=$file
แทนเพื่อให้บรรลุผลเดียวกัน ขออภัยในความสับสนใด ๆ
สิ่งสำคัญที่ควรทราบคือคุณไม่ควรแยกวิเคราะห์ผลลัพธ์ของ ls ไม่เคย
ls
แนวทางที่ใช้หากมีการเชื่อมโยงเวลาในการแก้ไขของเป้าหมายของการเชื่อมโยงจะได้รับการพิจารณา (เพิ่ม-L
ตัวเลือกที่ls
จะได้รับพฤติกรรมเดียวกันที่นั่น)
ฉันคิดว่าตัวเลือกที่ดีที่สุดที่นี่คือ:
ls -rf $MY_DIR/FILE.*.xml
if [ $? -eq 0 ]; then
INPUT_FILE=`ls -rt $MY_DIR/FILE.*.xml|head -1|xargs basename `
else
echo "Error!"
fi
หากไม่มีไฟล์ดังนั้นโค้ดส่งคืนของ ls คือ 2 แต่หากพบว่าไฟล์บางไฟล์จะเป็น 0
ls
จะไม่ล้มเหลว