भले ही यह एक पुराना सवाल है, लेकिन मुझे लगता है कि यह एक बारहमासी सवाल है, और एक अधिक सामान्य, स्पष्ट समाधान उपलब्ध है जो अब तक सुझाया गया है। क्रेडिट जहां क्रेडिट की वजह से है: मुझे यकीन नहीं है कि मैं स्टीफन चेज़ेलस के <>
अद्यतन ऑपरेटर के उल्लेख पर विचार किए बिना इसके साथ आया हूं ।
बॉर्न शेल में अपडेट के लिए एक फाइल खोलना सीमित उपयोगिता का है। शेल आपको किसी फ़ाइल की तलाश करने का कोई रास्ता नहीं देता है, और इसकी नई लंबाई निर्धारित करने का कोई तरीका नहीं है (यदि पुराने की तुलना में छोटा है)। लेकिन यह आसानी से है, इसलिए आसानी से मुझे आश्चर्य है कि यह मानक उपयोगिताओं में नहीं है /usr/bin
।
यह काम:
$ grep -n foo T
8:foo
$ (exec 4<>T; grep foo T >&4 && ftruncate 4) && nl T;
1 foo
जैसा कि यह (स्टीफन से हैट टिप):
$ { grep foo T && ftruncate; } 1<>T && nl T;
1 foo
(मैं GNU grep का उपयोग कर रहा हूँ। शायद कुछ बदल गया है क्योंकि उन्होंने अपना उत्तर लिखा है।)
को छोड़कर, आपके पास कोई / usr / bin / ftruncate नहीं है । C की एक दो दर्जन पंक्तियों के लिए, आप नीचे देख सकते हैं। यह ftruncate उपयोगिता एक मनमाना फ़ाइल डिस्क्रिप्टर को एक मनमाना लंबाई तक पहुंचाती है , जो मानक आउटपुट और वर्तमान स्थिति के लिए डिफ़ॉल्ट है।
उपरोक्त आदेश (पहला उदाहरण)
T
अद्यतन के लिए फ़ाइल विवरणक 4 खोलता है । बस के रूप में खुला (2) के साथ, इस तरह से फ़ाइल को खोलने पर वर्तमान ऑफसेट 0 पर स्थित है।
- grep
T
सामान्य रूप से प्रक्रिया करता है , और शेल T
डिस्क्रिप्टर 4 के माध्यम से अपने आउटपुट को रीडायरेक्ट करता है ।
- ftruncate डिस्क्रिप्टर 4 पर ftruncate (2) को कॉल करता है, जो वर्तमान ऑफ़सेट के मान की लंबाई निर्धारित करता है (ठीक उसी जगह जहां grep ने इसे छोड़ा था)।
उपधारा फिर बाहर निकलता है, विवरणक 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 वर्ष पुराना है, मैं यह कहने जा रहा हूं कि यह समाधान अप्रतिष्ठित है। यह एक नया डिस्क्रिप्टर खोलने के लिए निष्पादन का लाभ उठाता है , और <>
ऑपरेटर, जो दोनों आर्कन हैं। मैं एक मानक उपयोगिता के बारे में नहीं सोच सकता जो फ़ाइल डिस्क्रिप्टर द्वारा एक इनोड को हेरफेर करता है। (सिंटैक्स हो सकता है ftruncate >&4
, लेकिन मुझे यकीन नहीं है कि एक सुधार है।) यह कैम के सक्षम, खोजपूर्ण उत्तर की तुलना में काफी कम है। यह स्टीफ़न, IMO की तुलना में थोड़ा स्पष्ट है, जब तक कि आप पर्ल को मुझसे अधिक पसंद नहीं करते। मुझे आशा है कि किसी को यह उपयोगी लगता है।
एक ही काम करने का एक अलग तरीका लेसेक (2) का एक निष्पादन योग्य संस्करण होगा जो वर्तमान ऑफसेट की रिपोर्ट करता है; आउटपुट का उपयोग / usr / bin / truncate के लिए किया जा सकता है , जो कुछ लिनक्स प्रदान करते हैं।