2012-09-06 14 views
11

उदाहरणकैसे पता चलेगा कि लूप में फ़ाइल आखिरी है?

for FILE in $DIR/* 
do 
    if(<is last File>) 
    doSomethingSpecial($FILE) 
    else 
    doSomethingRegular($FILE) 
    fi 
done 

यदि वर्तमान फ़ाइल सरणी में पिछले एक है की जाँच करने के <is last file> के लिए क्या कॉल करने के लिए?

क्या मेरे द्वारा सरणी की लंबाई को जांच किए बिना कोई आसान अंतर्निहित चेक है?

+0

नहीं, मैं न केवल पिछले फ़ाइल पर कार्रवाई चाहते हैं, लेकिन (मेरे पाश उदाहरण की तरह) प्रत्येक फ़ाइल पर कार्रवाई करने और बस पर एक और ऑपरेशन करना अंतिम फाइल –

+1

क्षमा करें अगर मैं स्पष्ट नहीं था, तो आप अंतिम फ़ाइल नाम का पता लगाने के लिए ls + tail का उपयोग कर सकते हैं। फिर अपने लूप में फ़ाइल नाम -ईक चेक की जांच करें। यह स्थिति होगी। मैं अपने * निक्स कंसोल से पहले नहीं हूं, बस एक विचार दे रहा हूं – questzen

+0

'ls | पूंछ 'काम नहीं करेगा अगर अंतिम फ़ाइल नाम में एक नई रेखा है (एक दुर्लभ घटना है, लेकिन असंभव नहीं है)। – chepner

उत्तर

8

मुझे यह बताने का कोई तरीका नहीं है कि आप लूप में किसी सूची के अंतिम तत्व को संसाधित कर रहे हैं। आप एक सरणी इस्तेमाल कर सकते हैं हालांकि, पिछले तत्व लेकिन सब कुछ खत्म पुनरावृति, और फिर पाश के बाहर पिछले तत्व पर कार्रवाई:

files=($DIR/*) 
for file in "${files[@]::${#files[@]}-1}" ; do 
    doSomethingRegular "$file" 
done 
doSomethingSpecial "${files[@]: -1:1}" 

विस्तार ${files[@]:offset:length}offset पर शुरू सभी तत्वों का मूल्यांकन (या शुरुआत खाली हो तो) length तत्वों के लिए। ${#files[@]}-1 शून्य से 1.

${files[@]: -1:1} सरणी में तत्वों की संख्या पिछले तत्व का आकलन करती है - -1 छोर से, लंबाई 1. अंतरिक्ष आवश्यक के रूप में :-: - को अलग तरह से व्यवहार कर रहा है।

+2

'bash' 4.x से शुरू हो रहा है (सुनिश्चित नहीं है कि 4.0 या बाद की बिंदु रिलीज), आप' $ {files [@]: -1: 1} के बजाय '$ {files [-1]}' का उपयोग कर सकते हैं। । – chepner

4

इस

LAST_FILE="" 
for f in * 
do 
     if [ ! -z $LAST_FILE ] 
     then 
       echo "Process file normally $LAST_FILE" 
     fi 
     LAST_FILE=$f 
done 
if [ ! -z $LAST_FILE ] 
then 
     echo "Process file as last file $LAST_FILE" 
fi 

उत्पादन

bash[1051]: ls 
1 2 3 4 
bash[1052]: sh ../last_file.sh 
Process file normally 1 
Process file normally 2 
Process file normally 3 
Process file as last file 4 
+0

यह केवल सामान्य फ़ाइल को सामान्य रूप से संसाधित करेगा। – chepner

+0

गलत। मैंने आउटपुट दिखाने के लिए अपना जवाब संपादित किया है। –

+0

क्षमा करें, मैंने आपके कोड को सावधानीपूर्वक पर्याप्त नहीं पढ़ा। मुझे लगता है कि मुझे याद आया कि आप सीधे '$ f' पर काम नहीं कर रहे थे, लेकिन 'LAST_FILE' पर। – chepner

12

क्या होगा यदि वर्तमान फ़ाइल सरणी में पिछले एक है की जाँच करने के लिए कॉल करने के लिए प्रयास करें?

शुरुआत के लिए, आप एक सरणी का उपयोग नहीं कर रहे हैं। यदि आप तो थे यह आसान होगा:

declare -a files 
files=($DIR/*) 
pos=$((${#files[*]} - 1)) 
last=${files[$pos]} 

for FILE in "${files[@]}" 
do 
    if [[ $FILE == $last ]] 
    then 
    echo "$FILE is the last" 
    break 
    else 
    echo "$FILE" 
    fi 
done 
+0

धन्यवाद आप, यह समाधान ठीक काम करता है। लेकिन मैं थोड़ा निराश हूं, ऐसा करने के लिए निम्न स्तर के चरणों के बिना, किसी भी तरह का 'अच्छा' तरीका नहीं है। –

+0

अन्य भाषाओं, उदा। पर्ल और पायथन, नकारात्मक ऑफसेट के साथ दाएं से इंडेक्सिंग की इजाजत देते हैं, इसलिए आखिरी है [-1]। हो सकता है कि आपको अपनी भाषा को कुछ और शक्तिशाली में अपग्रेड करना चाहिए? आप वैसे भी ऐसा क्यों करना चाहते हैं? – cdarke

+1

4.x श्रृंखला में कभी-कभी, 'bash' ने नकारात्मक सरणी ऑफसेट को अनुमति देना शुरू किया। – chepner

1

आप, स्थितीय मापदंडों का दुरुपयोग कर सकते हैं क्योंकि वे एक सरणी, की तरह ही काम करते हैं लेकिन एक छोटे से हेरफेर करने के लिए आसान है। आपको या तो पुराने स्थिति पैरामीटर को सहेजना चाहिए, या सबहेल में निष्पादित करना चाहिए।  

# Method 1: use a subshell. Slightly cleaner, but you can't always 
# do this (for example, you may need to affect variables in the current 
# shell 
files=($DIR/*) 

(
    set -- "${files[@]}" 
    until (($# == 1)); do 
     doSomethingRegular "$1" 
     shift 
    done  
    doSomethingSpecial "$1" 
) 

# Method 2: save the positional parameters. A bit uglier, but 
# executes everything in the same shell. 

files=($DIR/*) 
oldPP=("[email protected]") 
set -- "${files[@]}" 
until (($# == 1)); do 
    doSomethingRegular "$1" 
    shift 
done  
doSomethingSpecial "$1" 
set -- "${oldPP[@]}" 
2

क्या एक फ़ाइल पिछले एक बनाता है? क्या इसके बारे में कुछ खास है? क्या यह नाम से क्रमबद्ध होने पर सबसे बड़ा नाम वाला फ़ाइल है?

शायद आप फ़ाइल नाम पीछे ले सकते हैं। फिर, यह पहली फ़ाइल है जिसे आप विशेष रूप से इलाज करना चाहते हैं, न कि अंतिम। आखिरी बार पता लगाने से पहले एक आसान काम है:

for file in $(ls -r1 $dir) 
do 
    if [ ! $processedLast ] 
    then 
     doSomethingSpecial($file) 
     processedLast=1 
    else 
     doSomethingRegular($file) 
    fi 
done 

कोई सरणी की आवश्यकता नहीं है। असल में, मुझे स्थितित्मक पैरामीटर का उपयोग करने के बारे में chepner का जवाब पसंद है।

2

आप फ़ाइलों की कुल संख्या को खोजने के लिए उपयोग का उपयोग कर सकते हैं। फिर जब आप लूप में हैं तो कुल संख्या में गिनती करें और अपना कार्य पूरा करें जब कुल गिनती i.e, अंतिम फ़ाइल के बराबर होती है।

f=0 
tot_files=`find . -iname '*.txt' | wc -l` 
for FILE in $DIR/* 
do 
f=($f+1) 
if [[ $f == $tot_files ]];then 
carryout your task 
fi 
done 
1

बिल्डिंग @cdarke (https://stackoverflow.com/a/12298757/415523) से वर्तमान उच्चतम मतदान जवाब पर, अगर मान (बजाय विशेष रूप से डिस्क पर फ़ाइलों) की एक सामान्य सरणी पर देख रहे हैं, पाश कोड के रूप में किया जाएगा इस प्रकार है:

a 
b 
c 
d 
e 
c is the last 

यह सुनिश्चित करता है कि केवल पिछले सरणी में आइटम alternat से चलाता है:

declare -a array 
declare -i length current 

array=(a b c d e c) 
length=${#array[@]} 
current=0 

for VALUE in "${array[@]}"; do 
    current=$((current + 1)) 

    if [[ "$current" -eq "$length" ]]; then 
    echo "$VALUE is the last" 
    else 
    echo "$VALUE" 
    fi 
done 

यह आउटपुट पैदावार ive कार्रवाई और यदि, सरणी में कोई अन्य आइटम अंतिम मान को डुप्लिकेट करता है, तो वैकल्पिक क्रिया नहीं है जो पहले डुप्लिकेट के लिए बुलाया जाता है।

फ़ाइलों के सरणी के मामले में किसी विशिष्ट निर्देशिका में, उदा।

array=($DIR/*) 

... यह शायद का कोई खास महत्व (जब तक आप एक वास्तव में अजीब फाइल सिस्टम है!) है, क्योंकि एक ही निर्देशिका के अलग-अलग फ़ाइल नाम लगभग निश्चित रूप से अद्वितीय हैं

+0

फिर भी बहुत साफ नहीं है, लेकिन एक सरल समाधान जो काम करता है, यहां तक ​​कि निरंतर (इंडेक्स के बीच छेद) सरणी के साथ भी। धन्यवाद। –

0

यह पुराने सवाल है - लेकिन @GregReynolds के उत्तर पर बिल्डिंग कृपया इस एक-लाइनर का उपयोग करें यदि आदेश केवल अंतिम पास के पैरामीटर द्वारा भिन्न होते हैं। एक लाइनर प्रेमियों

(ff="" ; for f in * "" ; do [ -n "$ff" ] && echo $(${f:+false} && echo $ff alternate params here || echo normal params $ff) ; ff=$f ; done) के लिए बदसूरत, बदसूरत कोड normal params 1 normal params 2 normal params 3 4 alternate params here

संबंधित मुद्दे