2008-09-13 27 views
74

मैंने हमेशा सोचा है कि लोग कमांड लाइन में पिछली पंक्ति को कैसे अपडेट करते हैं। लिनक्स में wget कमांड का उपयोग करते समय इसका एक शानदार उदाहरण है।कमांड लाइन को एनिमेट कैसे करें?

[======>                                        ] 37%: यह तरह की एक ASCII लोडिंग बार है कि इस तरह दिखता है बनाता है

और निश्चित रूप से लो डिंग बार चाल और प्रतिशत परिवर्तन, लेकिन यह एक नई लाइन नहीं बनाता है। मैं यह नहीं समझ सकता कि यह कैसे करें। क्या कोई मुझे सही दिशा दिखा सकता है?

उत्तर

42

दो तरीके मैं के बारे में पता यह करने के लिए कर रहे हैं:

  • अपनी लाइन
  • curses पैकेज का प्रयोग करें को मिटाने के लिए बैकस्पेस भागने चरित्र ('\ ख') का प्रयोग करें, यदि अपनी पसंद के प्रोग्रामिंग भाषा इसके लिए बाइंडिंग है।

और Google ने ANSI Escape Codes का खुलासा किया, जो एक अच्छा तरीका प्रतीत होता है। संदर्भ के लिए, सी में एक समारोह है ++ यह करने के लिए:

void DrawProgressBar(int len, double percent) { 
    cout << "\x1B[2K"; // Erase the entire current line. 
    cout << "\x1B[0E"; // Move to the beginning of the current line. 
    string progress; 
    for (int i = 0; i < len; ++i) { 
    if (i < static_cast<int>(len * percent)) { 
     progress += "="; 
    } else { 
     progress += " "; 
    } 
    } 
    cout << "[" << progress << "] " << (static_cast<int>(100 * percent)) << "%"; 
    flush(cout); // Required. 
} 
+7

मान लिया जाये कि वह एक Win32 कंसोल अनुप्रयोग चल रहा है (डॉस) विंडोज के एक हालिया संस्करण (यानी 2000+) पर, एएनएसआई एस्केप कोड बिल्कुल काम नहीं करेंगे। जैसा कि आप से जुड़े विकिपीडिया लेख में कहा गया है। –

+0

यदि आप विंडोज़ पर एएनएसआई एस्केप सीक्वेंस के साथ काम करते हैं तो आप Ansicon का उपयोग कर सकते हैं। https://github.com/adoxa/ansicon –

56

एक तरीका यह बार-बार वर्तमान प्रगति के साथ पाठ की पंक्ति को अद्यतन करने के लिए है क्या करना है। उदाहरण के लिए:

def status(percent): 
    sys.stdout.write("%3d%%\r" % percent) 
    sys.stdout.flush() 

ध्यान दें कि मैं sys.stdout.write बजाय print इस्तेमाल किया (इस अजगर है), क्योंकि print स्वचालित रूप से प्रिंट "\ r \ n" (गाड़ी-लौटने नई लाइन) प्रत्येक पंक्ति के अंत में। मैं बस कैरिज-रिटर्न चाहता हूं जो कर्सर को लाइन की शुरुआत में लौटाता है। इसके अलावा, flush() आवश्यक है क्योंकि डिफ़ॉल्ट रूप से, sys.stdout केवल एक नई लाइन के बाद अपने आउटपुट को फ़्लश करता है (या इसके बफर पूर्ण होने के बाद)।

+0

और printf और '\ r' के साथ 'c' में वही है। –

+0

फ्लश() 'के बाद" फ़्लश "क्या है? बस जिज्ञासा ... – Nearoo

+0

@Nearoo आम तौर पर एक नई लाइन (\ n) लिखा जाता है जब तक stdout अपने आउटपुट बफर। फ्लशिंग आंशिक रेखा तुरंत दिखाई देती है। –

3

पावरशेल में एक लिखें-प्रगति cmdlet है जो एक इन-कंसोल प्रगति पट्टी बनाता है जिसे आप अपनी स्क्रिप्ट चलाने के रूप में अपडेट और संशोधित कर सकते हैं।

0

यदि आप एक स्क्रिप्टिंग भाषा का उपयोग कर रहे हैं तो आप इसे प्राप्त करने के लिए "ट्यूट कप" कमांड का उपयोग कर सकते हैं ... पीएस यह एक लिनक्स/यूनिक्स चीज है जहां तक ​​मुझे पता है ...

2

Greg's answer पर फ़ॉलो करने के रूप में, यहां उनके फ़ंक्शन का विस्तारित संस्करण है जो आपको बहु-पंक्ति संदेश प्रदर्शित करने की अनुमति देता है; बस उन स्ट्रिंग्स की सूची या टुपल में पास करें जिन्हें आप प्रदर्शित/रीफ्रेश करना चाहते हैं।

def status(msgs): 
    assert isinstance(msgs, (list, tuple)) 

    sys.stdout.write(''.join(msg + '\n' for msg in msgs[:-1]) + msgs[-1] + ('\x1b[A' * (len(msgs) - 1)) + '\r') 
    sys.stdout.flush() 

नोट: मैं केवल इस एक linux टर्मिनल का उपयोग, इसलिए अपने लाभ विंडोज आधारित सिस्टम पर भिन्न हो सकते हैं परीक्षण किया है।

+0

विंडोज (7sp1x64): काम नहीं करता है। – n611x007

+0

@naxa क्या ग्रेग का उत्तर (उपर्युक्त) आपके लिए काम करता है? यह न्यूलाइन चरित्र के साथ सबसे अधिक संभावना है। '\ R' को '\ r \ n' के साथ बदलने का प्रयास करें। – Blaker

+0

ग्रेग का काम करता है, इसलिए एक पंक्ति पर यह काम करता है, लेकिन मैंने बहु-लाइन संदेश अपडेट करने की कोशिश की। :) मैंने आपकी स्क्रिप्ट में '\ n' से' \ r \ n' को बदल दिया है, लेकिन फिर भी यह विंडोज़ पर काम नहीं कर सका (क्या आप?)। मुझे '← [ए ← [ए' कुछ संदेशों के बाद, मुझे संदेह है कि '' x_b [ए 'अनुक्रम' cmd.exe' में क्या नहीं करना चाहिए। – n611x007

3

यहाँ अपने प्रश्न के लिए जवाब है ... (अजगर)

def disp_status(timelapse, timeout): 
    if timelapse and timeout: 
    percent = 100 * (float(timelapse)/float(timeout)) 
    sys.stdout.write("progress : ["+"*"*int(percent)+" "*(100-int(percent-1))+"]"+str(percent)+" %") 
    sys.stdout.flush() 
    stdout.write("\r \r") 
4
नीचे

मेरा उत्तर है, का उपयोग खिड़कियों एपीआई Consoles(Windows), सी की कोडिंग

/* 
* file: ProgressBarConsole.cpp 
* description: a console progress bar Demo 
* author: lijian <[email protected]> 
* version: 1.0 
* date: 2012-12-06 
*/ 
#include <stdio.h> 
#include <windows.h> 

HANDLE hOut; 
CONSOLE_SCREEN_BUFFER_INFO bInfo; 
char charProgress[80] = 
    {"================================================================"}; 
char spaceProgress = ' '; 

/* 
* show a progress in the [row] line 
* row start from 0 to the end 
*/ 
int ProgressBar(char *task, int row, int progress) 
{ 
    char str[100]; 
    int len, barLen,progressLen; 
    COORD crStart, crCurr; 
    GetConsoleScreenBufferInfo(hOut, &bInfo); 
    crCurr = bInfo.dwCursorPosition; //the old position 
    len = bInfo.dwMaximumWindowSize.X; 
    barLen = len - 17;//minus the extra char 
    progressLen = (int)((progress/100.0)*barLen); 
    crStart.X = 0; 
    crStart.Y = row; 

    sprintf(str,"%-10s[%-.*s>%*c]%3d%%", task,progressLen,charProgress, barLen-progressLen,spaceProgress,50); 
#if 0 //use stdand libary 
    SetConsoleCursorPosition(hOut, crStart); 
    printf("%s\n", str); 
#else 
    WriteConsoleOutputCharacter(hOut, str, len,crStart,NULL); 
#endif 
    SetConsoleCursorPosition(hOut, crCurr); 
    return 0; 
} 
int main(int argc, char* argv[]) 
{ 
    int i; 
    hOut = GetStdHandle(STD_OUTPUT_HANDLE); 
    GetConsoleScreenBufferInfo(hOut, &bInfo); 

    for (i=0;i<100;i++) 
    { 
     ProgressBar("test", 0, i); 
     Sleep(50); 
    } 

    return 0; 
} 
+0

'bInfo' कहां परिभाषित किया गया है? –

13

गुप्त n \ r \ n पर और रेखा के या \ के बजाय केवल \ r मुद्रित करने के लिए है।

\ r गाड़ी वापसी कहा जाता है और यह लाइन

\ N लाइन फ़ीड कहा जाता है की शुरुआत में कर्सर ले जाता है और यह अगली पंक्ति कंसोल में पर कर्सर ले जाता है। यदि आप केवल पहले लिखित रेखा को ओवरराइट करते हैं तो आप इसका उपयोग करते हैं।

[   ] 

तो प्रत्येक टिक

\r[=   ] 

\r[==  ] 

... 

\r[==========] 

और इतने पर के लिए एक संकेत जोड़ें: तो सबसे पहले निम्नलिखित की तरह एक लाइन में लिखें। आप 10 वर्णों का उपयोग कर सकते हैं, प्रत्येक 10% का प्रतिनिधित्व करते हैं। इसके अलावा, अगर आप काम पूरा हो जाने संदेश प्रदर्शित करना चाहते हैं, मत भूलना भी इतना है कि तुम इतनी तरह पहले से लिखा बराबर चिह्न के ऊपर लिख पर्याप्त सफेद वर्ण जोड़ने के लिए: नहीं

\r[done  ] 
+1

यह पूरी तरह से काम किया। यह भी मेरी राय में बहुत आसान है। – Erutan409