प्रत्यय जोड़ने के लिए फ़ाइलों का नाम बदलना


13

मुझे वर्तमान कार्य निर्देशिका में सभी फ़ाइलों का नाम बदलने के लिए एक कमांड की आवश्यकता है, इस तरह से कि नया फ़ाइल नाम पुराने जैसा ही होगा, लेकिन मूल फाइलों की लाइनों की संख्या के अनुरूप एक प्रत्यय सहित (जैसे कि फ़ाइल fमें 10 हैं लाइनों को फिर से नाम देना चाहिए f_10)।

यहाँ मेरा (गैर-काम करने का) प्रयास है:

 linenum=$(wc -l); find * -type f | grep -v sh | rename 's/^/ec/'*

आप इसका जवाब दे सकते हैं! (यदि यह मौजूदा उत्तरों में कुछ नया जोड़ता है - लेकिन ऐसा लगता है कि यह ऐसा करता है)
वोल्कर सिएगल

जवाबों:


13

कैसा रहेगा:

for f in *; do mv "$f" "$f"_$(wc -l < "$f"); done

उदाहरण के लिए:

$ wc -l *
 10 file1
 40 file2
100 file3
$ ls
file1_10  file2_40  file3_100

यदि आप एक्सटेंशन रखना चाहते हैं (यदि मौजूद है), तो इसके बजाय इसका उपयोग करें:

for f in *; do 
    ext=""; 
    [[ $f =~ \. ]] && ext="."${f#*.}; 
    mv "$f" "${f%%.*}"_$(wc -l < "$f")$ext; 
done

धन्यवाद टेराडॉन! यह कमांड लाइन काम पूरा करने के लिए लगती है लेकिन मैं डॉट (।) से (_) कैसे बदल सकता हूं? इसके अलावा, जैसा कि मेरी स्क्रिप्ट फ़ोल्डर के अंदर है, इसका नाम भी बदल दिया गया है और इसलिए मेरी स्क्रिप्ट को एक बार निष्पादित करने की अनुमति मिलती है (क्योंकि स्क्रिप्ट का नाम बदल जाता है ...)
मार्टिन येओबा

@MartinYeboah के लिए अद्यतन जवाब देखें _। स्क्रिप्ट के लिए, क्या स्क्रिप्ट? इसे कमांड लाइन से चलाया जाना चाहिए, स्क्रिप्ट की कोई आवश्यकता नहीं है। यदि आप केवल कुछ फ़ाइलों से मिलान करना चाहते हैं in *, तो, उदाहरण के लिए, in *txtया कुछ बदल सकते हैं।
टेराडॉन

बहुत बहुत धन्यवाद;) मैं पूरी तरह से भूल गया कि इसे कमांड लाइन से निष्पादित किया जाना चाहिए :)
मार्टिन येओबा

मुझे लगता wc -l < $fहै कि grep के बजाय समझना आसान होगा (और शायद बेहतर प्रदर्शन करने के लिए लेकिन मैंने ऐसा नहीं किया है)।
मुसकिन

@musiKk हाँ, लेकिन चूंकि अन्य उत्तर उपयोग कर रहे हैं wc, मैं एक अलग दृष्टिकोण दिखाना चाहता था। लेकिन ठीक है, पर्याप्त निष्पक्ष।
टेराडॉन

10

आप इस एक लाइनर की कोशिश कर सकते हैं:

find . -maxdepth 1 -type f -exec bash -c 'mv -i "$1" "$1.$(wc -l <"$1")"' _ {} \;
  • यह वर्तमान कार्यशील निर्देशिका में सभी फ़ाइलें ( find . -maxdepth 1 -type f) मिलेगा

  • फिर हम लाइनों की संख्या को बढ़ाने के लिए फ़ाइलों का नाम बदलने के लिए मिली फाइलों पर एक शेल इंस्टेंस चला रहे हैं।

उदाहरण :

$ ls
bar.txt spam.txt foo.txt

$ find . -maxdepth 1 -type f -exec bash -c 'mv -i "$1" "$1.$(wc -l <"$1")"' _ {} \;

$ ls
bar.txt.12 foo.txt.24 spam.txt.7

6

एक और तरीका है जो एक्सटेंशन (यदि मौजूद है) का उपयोग करके संरक्षित करता है rename:

for f in *; do rename -n "s/([^.]+)(\.?.*)/\$1_$(< "$f" wc -l)\$2/" "$f"; done

यदि परिणाम अपेक्षित है, तो -nविकल्प को हटा दें :

for f in *; do rename "s/([^.]+)(\.?.*)/\$1_$(< "$f" wc -l)\$2/" "$f"; done

renamegreat =) +1
AB

1
यह abcd पर विफल नहीं होगा? दूसरे कैप्चर ग्रुप को बदलें (\.?[^\.]+)
ps95

@ prakharsingh95 यह सच है, हालाँकि (\.?[^\.]+)या तो ठीक नहीं है क्योंकि यह केवल दूसरे डॉट तक मेल खाएगा और लगातार डॉट्स के साथ फ़ाइल नाम से मेल नहीं खाएगा या बिना डॉट के समाप्त होगा। यह एक आसान समाधान कठिन नहीं है, एकमात्र तरीका दो प्रतिस्थापन करना प्रतीत होता है।
कोस

@ आप सही हैं। कैसे ([^ \।] +)। *? ([^ \।] + $) मैं इष्टतमता के बारे में निश्चित नहीं हूं। वर्किंग फिडेल
ps95

1
@ prakharsingh95 आप .चरित्र वर्गों के अंदर बचना नहीं चाहते हैं।
टेराडॉन

5

का उपयोग कर find:

find . -maxdepth 1 -type f -print0 | while read -d $'\0' f; do mv "$f" "$f"_$(grep -c . "$f"); done

उदाहरण

% wc -l *
  3 doit
  5 foo

% find . -maxdepth 1 -type f -print0 | while read -d $'\0' f; do mv "$f" "$f"_$(grep -c . "$f"); done

% wc -l *                         
  3 doit_3
  5 foo_5

क्यों -name "*"? परीक्षणों से बचा? ;)
कोस

1
@kos पुरानी आदत: \
एबी

3

बस मज़े के लिए और एक समाधान के साथ गिगल्स rename। चूँकि renameएक पर्ल टूल है जो एक मनमाना स्ट्रिंग को स्वीकार करता है जो कि eval'd है, आप सभी प्रकार के शेंनिगन्स कर सकते हैं। काम करने के लिए लगता है कि एक समाधान निम्नलिखित है:

rename 's/.*/open(my $f, "<", $_);my $c=()=<$f>;$_."_".$c/e' *

दिलचस्प विचार +1
एबी

2

स्क्रिप्ट बलो में कई मामले शामिल होते हैं: एकल बिंदु और एक्सटेंशन (फ़ाइल। टेक्स्ट), कई डॉट्स और एक्सटेंशन (फ़ाइल.1.txt), लगातार डॉट्स (फ़ाइल..ऑफ़ोबार.टेक्स्ट), और फ़ाइल नाम (फ़ाइल) में डॉट्स। फ़ाइल ..)।

लिपी

#!/bin/bash
# Author: Serg Kolo
# Date:  June 25,2015
# Description: script to rename files to file_numlines
# written for http://askubuntu.com/q/640430/295286

# Where are the files ?
WORKINGDIR=/home/xieerqi/substitutions
# Where do you want them to go ?
OUTPUTDIR=/home/xieerqi/substitutions/output

for file in $WORKINGDIR/* ;do 
    FLAG=0
    EXT=$(printf "%s" "$file" | awk -F'.' '{printf "%s",$NF }' )  # extension, last field of dot-separated string
    # EXT="${file##*.}" # Helio's advice is to use parameter expansion, but I dont know how to use it
    if [ -z $EXT ]; then # we have a dot at the end case file. or something
        # so we gotta change extension and filename
        EXT=""
        FILENAME=$(printf "%s" "$file" | awk -F '/' '{ print $NF}' )
        # set flag for deciding how to rename
        FLAG=1
    else
        FILENAME=$( printf "%s" "$file" | awk -F '/' -v var=$EXT '{gsub("."var,"");print $NF}'   ) # filename, without path, lst in
    fi

    NUMLINES=$(wc -l "$file" | awk '{print $1}') # line count

    if [ $FLAG -eq 0 ];then
         echo "$file" renamed as "$OUTPUTDIR"/"$FILENAME"_"$NUMLINES"."$EXT"
        # cp "$file" "$OUTPUTDIR"/"$FILENAME"_"$NUMLINES"."$EXT" # uncomment when necessary
    else
        echo "$file" renamed as "$OUTPUTDIR"/"$FILENAME"_"$NUMLINES""$EXT"
        # cp "$file" "$OUTPUTDIR"/"$FILENAME"_"$NUMLINES""$EXT" # uncomment when necessary
    fi

    #printf "\n"

done

कार्रवाई में स्क्रिप्ट

$./renamer.sh                                                                                                           
/home/xieerqi/substitutions/file. renamed as /home/xieerqi/substitutions/output/file._0
/home/xieerqi/substitutions/file.. renamed as /home/xieerqi/substitutions/output/file.._0
/home/xieerqi/substitutions/file.1.jpg renamed as /home/xieerqi/substitutions/output/file.1_3.jpg
/home/xieerqi/substitutions/file.1.test.jpg renamed as /home/xieerqi/substitutions/output/file.1.test_3.jpg
/home/xieerqi/substitutions/file.1.test.txt renamed as /home/xieerqi/substitutions/output/file.1.test_2.txt
/home/xieerqi/substitutions/file.1.txt renamed as /home/xieerqi/substitutions/output/file.1_2.txt
/home/xieerqi/substitutions/file.2.jpg renamed as /home/xieerqi/substitutions/output/file.2_3.jpg
/home/xieerqi/substitutions/file.2.test.jpg renamed as /home/xieerqi/substitutions/output/file.2.test_3.jpg
/home/xieerqi/substitutions/file.2.test.txt renamed as /home/xieerqi/substitutions/output/file.2.test_2.txt
/home/xieerqi/substitutions/file.2.txt renamed as /home/xieerqi/substitutions/output/file.2_2.txt
/home/xieerqi/substitutions/foo..bar.txt renamed as /home/xieerqi/substitutions/output/foo..bar_4.txt

ध्यान दें कि फ़ाइल में कोई रेखा नहीं है। और फ़ाइल .., इसलिए लाइन काउंट 0 है

स्क्रिप्ट की समीक्षा करने और संपादित सुझाव देने के लिए टेर्डन और हेलियो का विशेष धन्यवाद


2

चैट में @ हेलियो के साथ विकसित एक और बैश तरीका :

for file in *
do
    echo "$file"
    [[ -f "$file" ]] || continue
    [[ $file =~ (.*)(\.[^.]+)$ ]]
    cp "$file" "output/${BASH_REMATCH[1]:-$file}_$(wc -l < "$file")${BASH_REMATCH[2]}"
done

एक दूसरे के सिर के साथ अजीब दिखने वाला मोनोकल्ड लड़का ( (.*)(\.[^.]+)$) केवल उचित एक्सटेंशन ( .foo, नहीं ..) से मेल खाना चाहिए । यदि कोई एक्सटेंशन नहीं है, तो BASH_REMATCHसरणी खाली हो जाएगी। हम फ़ाइल नाम के लिए एक डिफ़ॉल्ट मान ${BASH_REMATCH[1]:-$file}का उपयोग करके और बस के रूप में विस्तार का उपयोग करके इसका लाभ उठा सकते हैं ।

डॉट फ़ाइलों को संभालने के लिए, आप टेर्डन और हेलियोfind द्वारा सुझाए अनुसार उपयोग कर सकते हैं ।

find -maxdepth 1 -type f -printf '%P\0' | 
while IFS= read -r -d '' file
do
    [[ $file =~ (.*)(\.[^.]+)$ ]]
    cp "$file" "output/${BASH_REMATCH[1]:-$file}_$(wc -l < "$file")${BASH_REMATCH[2]}"
done

+1: मैं कमांड के लिए स्पष्टीकरण नहीं दे पाऊंगा। ;-)
हेलियो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.