แม้ว่านี่จะเป็นคำถามเก่า แต่สำหรับฉันแล้วมันเป็นคำถามที่ยืนต้นและมีวิธีแก้ปัญหาที่ชัดเจนและชัดเจนกว่าที่เคยแนะนำ เครดิตที่ครบกำหนดเครดิต: ฉันไม่แน่ใจว่าฉันจะได้รับมันโดยไม่พิจารณาถึงการกล่าวถึง<>
ผู้ดำเนินการอัพเดท ของStéphane Chazelas
การเปิดไฟล์เพื่ออัปเดตในเชลล์เป้าหมายนั้นมีประโยชน์อย่าง จำกัด เชลล์ไม่ให้คุณค้นหาไฟล์และไม่มีวิธีตั้งค่าความยาวใหม่ (ถ้าสั้นกว่าเก่า) /usr/bin
แต่ที่แก้ได้ง่ายเพื่อให้ได้อย่างง่ายดายฉันประหลาดใจมันไม่อยู่ในกลุ่มสาธารณูปโภคมาตรฐานในการ
งานนี้:
$ grep -n foo T
8:foo
$ (exec 4<>T; grep foo T >&4 && ftruncate 4) && nl T;
1 foo
เช่นนี้ (ปลายหมวกถึงStéphane):
$ { grep foo T && ftruncate; } 1<>T && nl T;
1 foo
(ฉันใช้ grep GNU บางทีอาจมีบางอย่างเปลี่ยนแปลงไปตั้งแต่เขาเขียนคำตอบ)
ยกเว้นคุณไม่มี/ usr / bin / ftruncate สำหรับ C สองสามบรรทัดคุณสามารถดูด้านล่าง ยูทิลิตีftruncateนี้จะตัดทอนของไฟล์ descriptor ตามความยาวโดยพลการเริ่มต้นที่เอาต์พุตมาตรฐานและตำแหน่งปัจจุบัน
คำสั่งดังกล่าว (ตัวอย่างที่ 1)
- เปิด file descriptor 4
T
สำหรับการอัพเดท เช่นเดียวกับ open (2) การเปิดไฟล์ด้วยวิธีนี้ตำแหน่งออฟเซ็ตปัจจุบันที่ 0
- จากนั้นgrepจะประมวลผล
T
ตามปกติและเชลล์เปลี่ยนทิศทางเอาต์พุตไปยังT
ผ่าน descriptor 4
- ftruncate การเรียก ftruncate (2) บน descriptor 4 การตั้งค่าความยาวเป็นค่าของออฟเซ็ตปัจจุบัน (ตรงที่grepเหลือไว้)
จากนั้น subshell จะออก, ปิด descriptor 4 นี่คือftruncate :
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int
main( int argc, char *argv[] ) {
off_t i, fd=1, len=0;
off_t *addrs[2] = { &fd, &len };
for( i=0; i < argc-1; i++ ) {
if( sscanf(argv[i+1], "%lu", addrs[i]) < 1 ) {
err(EXIT_FAILURE, "could not parse %s as number", argv[i+1]);
}
}
if( argc < 3 && (len = lseek(fd, 0, SEEK_CUR)) == -1 ) {
err(EXIT_FAILURE, "could not ftell fd %d as number", (int)fd);
}
if( 0 != ftruncate((int)fd, len) ) {
err(EXIT_FAILURE, argc > 1? argv[1] : "stdout");
}
return EXIT_SUCCESS;
}
NB, ftruncate (2) ไม่สามารถพกพาได้เมื่อใช้ในวิธีนี้ สำหรับความรู้ทั่วไปอย่างแท้จริงให้อ่านไบต์ที่เขียนล่าสุดเปิดไฟล์ O_WRONLY ใหม่ค้นหาแสวงหาเขียนไบต์และปิด
ระบุว่าคำถามมีอายุ 5 ปีฉันจะบอกว่าวิธีนี้ไม่ชัดเจน มันใช้ประโยชน์จากexecเพื่อเปิด descriptor ใหม่และ<>
โอเปอเรเตอร์ซึ่งทั้งคู่เป็นอาร์เคน ฉันไม่สามารถนึกถึงยูทิลิตี้มาตรฐานที่จัดการ inode by file descriptor ได้ (ไวยากรณ์อาจเป็นไปได้ftruncate >&4
แต่ฉันไม่แน่ใจว่าเป็นการปรับปรุง) มันสั้นกว่าคำตอบเชิงสำรวจที่มีความสามารถของ camh อย่างมาก เป็นเพียงเล็กน้อยที่ชัดเจนกว่าของStéphane, IMO เว้นแต่คุณจะชอบ Perl มากกว่าที่ฉันทำ ฉันหวังว่าบางคนจะพบว่ามีประโยชน์
วิธีที่แตกต่างในการทำสิ่งเดียวกันจะเป็นเวอร์ชันที่สามารถเรียกทำงานได้ของ lseek (2) ที่รายงานออฟเซ็ตปัจจุบัน เอาต์พุตสามารถใช้สำหรับ/ usr / bin / truncateซึ่ง Linuxi บางตัวจัดเตรียมไว้