मैं अपनी फ़ाइल (तर्क) "bash का उपयोग करके" जगह पर संपादन करते हुए किसी भी कमांड को कैसे निष्पादित कर सकता हूं?


110

मेरे पास एक फाइल temp.txt है, जिसे मैं इसके साथ सॉर्ट करना चाहता हूं sort कमांड के बैश में ।

मैं मूल फ़ाइल को बदलने के लिए हल किए गए परिणाम चाहता हूं।

यह उदाहरण के लिए काम नहीं करता है (मुझे एक खाली फ़ाइल मिलती है):

sortx temp.txt > temp.txt

क्या यह अस्थायी फ़ाइलों की नकल का सहारा लिए बिना एक पंक्ति में किया जा सकता है?


EDIT: -oविकल्प के लिए बहुत अच्छा है sort। मैंने sortएक उदाहरण के रूप में अपने प्रश्न का उपयोग किया । मैं अन्य कमांड्स के साथ समान समस्या में चलता हूं:

uniq temp.txt > temp.txt.

क्या कोई बेहतर सामान्य उपाय है?


जवाबों:


171
sort temp.txt -o temp.txt

3
यह एक उत्तर है। मैं वास्तव में सोच रहा था कि क्या इस समस्या का कोई सामान्य समाधान है। उदाहरण के लिए अगर मैं "फ़ाइल" में सभी UNIQ लाइनें ढूंढना चाहता हूं, तो मैं -o
jm

यह सामान्य नहीं है, लेकिन आप जीएनयू के साथ यू का उपयोग कर सकते हैं
जेम्स

किसी ने समस्या को हल करने की अनुमति दी है जैसे sort --inplace *.txt? यह क्रेजी कूल होगा
सेह

@ ह्से यह कोशिश करें:find . -name \*.txt -exec sort {} -o {} \;
कीथ

29

एक sortसभी इनपुट को देखने के लिए इससे पहले कि यह उत्पादन के लिए शुरू कर सकते हैं की जरूरत है। इस कारण से, sortप्रोग्राम आसानी से फ़ाइल को इन-प्लेस करने के लिए एक विकल्प प्रदान कर सकता है:

sort temp.txt -o temp.txt

विशेष रूप से, GNUsort का प्रलेखन कहता है:

आम तौर पर, सॉर्ट आउटपुट-फ़ाइल खोलने से पहले सभी इनपुट को पढ़ता है, इसलिए आप सुरक्षित रूप से sort -o F Fऔर जैसे आदेशों का उपयोग करके किसी फ़ाइल को सुरक्षित रूप से सॉर्ट कर सकते हैं cat F | sort -o F। हालांकि, sortके साथ --merge( -m) तो एक आदेश की तरह, सभी इनपुट को पढ़ने से पहले आउटपुट फ़ाइल खोल सकते हैं cat F | sort -m -o F - Gसुरक्षित नहीं है के रूप में तरह लेखन शुरू हो सकता है Fइससे पहले कि catइसे पढ़ने के लिए किया जाता है।

जबकि बीएसडी का प्रलेखन sortकहता है:

यदि [] आउटपुट-फाइल इनपुट फाइलों में से एक है, तो आउटपुट को []] आउटपुट-फाइल पर सॉर्ट करने और लिखने से पहले एक अस्थायी फाइल में कॉपी कर दें।

uniqइनपुट को पूरा करने से पहले कमांड जैसे आउटपुट लिखना शुरू कर सकते हैं। ये कमांड आमतौर पर इन-प्लेस एडिटिंग का समर्थन नहीं करते हैं (और उनके लिए इस सुविधा का समर्थन करना कठिन होगा)।

आप आम तौर पर एक अस्थायी फ़ाइल के साथ इसके चारों ओर काम करते हैं, या यदि आप बिल्कुल एक मध्यवर्ती फ़ाइल होने से बचना चाहते हैं, तो आप इसे लिखने से पहले पूर्ण परिणाम को संग्रहीत करने के लिए एक बफर का उपयोग कर सकते हैं। उदाहरण के लिए, साथ perl:

uniq temp.txt | perl -e 'undef $/; $_ = <>; open(OUT,">temp.txt"); print OUT;'

यहां, पर्ल भाग uniqचर से पूरा आउटपुट पढ़ता है $_और फिर इस डेटा के साथ मूल फ़ाइल को ओवरराइट करता है। आप अपनी पसंद की स्क्रिप्टिंग भाषा में भी ऐसा कर सकते हैं, शायद बैश में भी। लेकिन ध्यान दें कि संपूर्ण फ़ाइल को संग्रहीत करने के लिए पर्याप्त मेमोरी की आवश्यकता होगी, बड़ी फ़ाइलों के साथ काम करते समय यह उचित नहीं है।


19

यहां एक अधिक सामान्य दृष्टिकोण है, यूनीक, सॉर्ट और व्हाट्सन के साथ काम करता है।

{ rm file && uniq > file; } < file

14
एक और सामान्य दृष्टिकोण, spongeअधिकताओं से cat file |frobnicate |sponge file:।
तोबू

3
@ टोबू: क्यों नहीं एक अलग जवाब के रूप में प्रस्तुत करें?
17

1
शायद यह नोट करना अच्छा है कि यह आवश्यक रूप से फ़ाइलों की अनुमति को संरक्षित नहीं करता है। आपके umask तय करते हैं कि नई अनुमतियाँ क्या होंगी।
चिंता

1
मुश्किल एक। क्या आप बता सकते हैं कि यह कैसे काम करता है?
patryk.beza

2
@ patryk.beza: क्रम में: इनपुट FD मूल फ़ाइल से खोली गई है; मूल निर्देशिका प्रविष्टि हटा दी गई है; पुनर्निर्देशन को संसाधित किया जाता है, उसी नाम के साथ एक नई खाली फ़ाइल बनाता है जो पुराने के पास होती थी; तब आज्ञा चलती है।
चार्ल्स डफी

10

स्पंज वारंट पर टोबू की टिप्पणी अपने आप में एक जवाब है।

Moreutils होमपेज से उद्धृत करने के लिए :

संभवतः अब तक के स्पुतनों में सबसे सामान्य उद्देश्य उपकरण स्पंज (1) है, जो आपको इस तरह की चीजें करने की सुविधा देता है:

% sed "s/root/toor/" /etc/passwd | grep -v joey | sponge /etc/passwd

हालाँकि, spongeएक ही समस्या से ग्रस्त है स्टीव जेसप यहाँ पर टिप्पणी करते हैं। यदि कोई भी कमांड पाइप लाइन में spongeफेल हो जाती है, तो मूल फाइल पर लिखा जाएगा।

$ mistyped_command my-important-file | sponge my-important-file
mistyped-command: command not found

उह-ओह, my-important-fileगया है।


1
स्पंज जानता है कि इसका उपयोग इनपुट फ़ाइल को बदलने के लिए किया जाएगा और यह शुरुआत में दौड़ की स्थिति से बचने के लिए एक अस्थायी फ़ाइल बनाता है। इसे काम करने के लिए, स्पंज को पाइप लाइन में अंतिम तत्व होना चाहिए और इसे आउटपुट फ़ाइल को स्वयं बनाने की अनुमति होनी चाहिए (उदाहरण के लिए शेल-स्तर आउटपुट पुनर्निर्देशन के विपरीत)। BTW: ऐसा लगता है कि 'असफल' मामले के लिए एक आसान स्रोत-कोड फिक्स एक पाइपफेल के मामले में अस्थायी फ़ाइल का नाम नहीं बदलने के लिए होगा (पता नहीं क्यों स्पंज में वह विकल्प नहीं है)।
ब्रेंट बर्नबर्न

मुझे लगता है कि यदि आप set -o pipefailअपनी स्क्रिप्ट की शुरुआत में जोड़ते हैं , तो त्रुटि को mistyped_command my-important-fileनिष्पादित करने से पहले स्क्रिप्ट को तुरंत बाहर कर दिया जाएगा sponge, इस प्रकार महत्वपूर्ण फ़ाइल को संरक्षित किया जाएगा।
एलुआन केरील-ईवन

6

यहाँ आप जाते हैं, एक पंक्ति:

sort temp.txt > temp.txt.sort && mv temp.txt.sort temp.txt

तकनीकी रूप से एक अस्थायी फ़ाइल की कोई प्रतिलिपि नहीं है, और 'mv' कमांड तत्काल होना चाहिए।


6
हम्म। मैं अभी भी temp.txt.sort को एक अस्थायी फ़ाइल कहूँगा।
जेसपर

5
यह कोड जोखिम भरा है, क्योंकि यदि कोई भी कार्य पूरा किए बिना किसी कारण से विफल रहता है, तो मूल ओवरराइट किया जाता है।
स्टीव जेसप

1
डिस्क स्थान की कमी एक प्रशंसनीय कारण है, या एक संकेत (उपयोगकर्ता हिट CTRL-C)।
स्टीव जेसप

5
यदि आप इसके बजाय कुछ इस तरह का उपयोग करना चाहते हैं && (तार्किक और); क्योंकि इसका उपयोग करने से यह सुनिश्चित हो जाएगा कि यदि कोई कमांड विफल रहता है तो उसे निष्पादित नहीं किया जाएगा। उदाहरण के लिए: cp backup.tar /root/backup.tar && rm backup.tar यदि आपके पास कॉपी करने के अधिकार नहीं हैं तो आप सुरक्षित रहेंगे क्योंकि फाइल डिलीट नहीं होगी
डेनियल

1
आपके सुझावों को ध्यान में रखने के लिए मेरे उत्तर को बदल दिया, धन्यवाद
davr

4

मुझे sort file -o fileउत्तर पसंद है लेकिन एक ही फ़ाइल नाम को दो बार लिखना नहीं चाहता।

BASH इतिहास विस्तार का उपयोग करना :

$ sort file -o !#^

प्रेस करते समय करंट लाइन की पहली आर्ग पकड़ लेता है enter

जगह में एक अनूठा प्रकार:

$ sort -u -o file !#$

वर्तमान लाइन में अंतिम arg को पकड़ लेता है।


3

कई ने -o विकल्प का उल्लेख किया है । यहाँ मैन पेज पार्ट है।

आदमी पृष्ठ से:

   -o output-file
          Write output to output-file instead of to the  standard  output.
          If  output-file  is  one of the input files, sort copies it to a
          temporary file before sorting and writing the output to  output-
          file.

3

यह अत्यधिक मेमोरी के लिए बाध्य होगा, लेकिन आप मेमोरी में इंटरमीडिएट डेटा को स्टोर करने के लिए awk का उपयोग कर सकते हैं, और फिर इसे वापस लिख सकते हैं।

uniq temp.txt | awk '{line[i++] = $0}END{for(j=0;j<i;j++){print line[j]}}' > temp.txt

मुझे लगता है कि यह संभव है >कि कमांड से पहले फाइल को रौंद दिया जाए ( uniqइस मामले में) इसे पढ़ता है।
मार्टिन

3

spongeअधिक सामान्य के साथ एक विकल्प sed:

sed -ni r<(command file) file

यह किसी भी आदेश (के लिए काम करता है sort, uniq, tac, ...) और का उपयोग करता है बहुत अच्छी तरह से जाना जाता sedहै -iविकल्प (यथा-स्थान संपादित फ़ाइलें)।

चेतावनी:command file पहले प्रयास करें क्योंकि फ़ाइलों को इन-प्लेस करना प्रकृति द्वारा सुरक्षित नहीं है।


व्याख्या

सबसे पहले, आपको बता रहे हैं sed(मूल) लाइनों (प्रिंट करने के लिए नहीं -nविकल्प ), और की मदद से sedकी rकमान और bashकी प्रक्रिया प्रतिस्थापन , द्वारा उत्पन्न सामग्री <(command file)उत्पादन सहेजा जाएगा जगह में


चीजों को और भी आसान बनाना

आप इस समाधान को एक फ़ंक्शन में लपेट सकते हैं:

ip_cmd() { # in place command
    CMD=${1:?You must specify a command}
    FILE=${2:?You must specify a file}
    sed -ni r<("$CMD" "$FILE") "$FILE"
}

उदाहरण

$ cat file
d
b
c
b
a

$ ip_cmd sort file
$ cat file
a
b
b
c
d

$ ip_cmd uniq file
$ cat file
a
b
c
d

$ ip_cmd tac file
$ cat file
d
c
b
a

$ ip_cmd
bash: 1: You must specify a command
$ ip_cmd uniq
bash: 2: You must specify a file

1

तर्क का उपयोग करें --output=या-o

बस FreeBSD पर कोशिश की:

sort temp.txt -otemp.txt

हालांकि सही है, यह केवल इस उत्तर
15



0

यदि आप sortप्रोग्राम का उपयोग करने पर जोर देते हैं , तो आपको एक मध्यवर्ती फ़ाइल का उपयोग करना होगा - मुझे नहीं लगता कि sortमेमोरी में सॉर्ट करने का कोई विकल्प है। जब तक आप यह गारंटी नहीं दे सकते कि स्टड / स्टडआउट के साथ कोई अन्य ट्रिक पूरी फाइल को फिट करने के लिए बड़े आकार की स्टडिन के लिए बफर आकार बड़ी है।

संपादित करें: मुझे शर्म आती है। sort temp.txt -o temp.txtउत्कृष्ट काम करता है।


मैंने क्यू को "इन-प्लेस" होने के रूप में भी पढ़ा था, लेकिन दूसरे रीड ने मुझे विश्वास दिलाया कि वह वास्तव में इसके लिए नहीं पूछ रहा था
एपीटेल

0

एक और समाधान:

uniq file 1<> file

यह ध्यान दिया जाना चाहिए कि <>चाल केवल इस मामले में काम करती है क्योंकि इसमें uniqविशेष है कि यह केवल इनपुट लाइनों को आउटपुट लाइनों पर कॉपी करता है, कुछ को रास्ते में छोड़ देता है। यदि अन्य कमांड (जैसे sed) का उपयोग किया गया था, जो इनपुट को बदल देगा (जैसे कि हर aमें बदल जाएगा aa), तो यह उन fileतरीकों से ओवरराइड कर सकता है जो किसी भी तरह से समझ में नहीं आते हैं और यहां तक ​​कि लूप को अनन्त रूप से प्रदान करते हैं, बशर्ते कि इनपुट पर्याप्त रूप से बड़ा हो (एक से अधिक) सिंगल रीड बफर)।
डेविड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.