Sonek eklemek için dosyaları yeniden adlandırma


13

Yeni dosya adı eski ile aynı olacak, ancak özgün dosyaların satır sayısına karşılık gelen bir sonek dahil olmak üzere geçerli çalışma dizinindeki tüm dosyaları yeniden adlandırmak için bir komut gerekir (örneğin, dosya f10 varsa satırları yeniden adlandırılmalıdır f_10).

İşte benim (çalışmayan) girişimim:

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

Bunu bir cevap verebilirsin! (Eğer mevcut cevaplara yeni bir şey eklerse - ama öyle görünüyorsa)
Volker Siegel

Yanıtlar:


13

Nasıl olur:

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

Örneğin:

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

Uzantıları (varsa) korumak istiyorsanız bunun yerine şunu kullanın:

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

Teşekkürler terdon! Bu komut satırı işi bitirmiş gibi görünüyor, ancak (.) noktasını (_) olarak nasıl değiştirebilirim? Ayrıca, komut dosyam klasör içinde olduğundan, aynı zamanda yeniden adlandırılır ve böylece komut dosyamın bir kez yürütülmesine izin verir (çünkü komut dosyası adı değişir ...)
Martin Yeboah

@ MartinYeboah için güncellenmiş cevaba bakınız _. Senaryoya gelince, hangi senaryo? Komut satırından çalıştırılmalıdır, komut dosyasına gerek yoktur. Eğer sadece bazı dosyaları eşleştirmek istiyorsanız, değiştirmek in *için, örneğin, in *txtya da bir şey.
terdon

çok teşekkürler;) Tamamen komut satırından yapılması gerektiğini unuttum :)
Martin Yeboah

wc -l < $fGrep yerine anlamak daha kolay olacağını düşünüyorum (ve belki de daha iyi yapmak için ama bunu kontrol etmedim).
musiKk

@musiKk evet, ancak diğer cevaplar kullanıldığından wcfarklı bir yaklaşım göstermek istedim. Ama tamam, yeterince adil.
terdon

10

Bu tek astarı deneyebilirsiniz:

find . -maxdepth 1 -type f -exec bash -c 'mv -i "$1" "$1.$(wc -l <"$1")"' _ {} \;
  • Bu işlem geçerli çalışma dizinindeki ( find . -maxdepth 1 -type f) tüm dosyaları bulur

  • Ardından, satır sayısını eklemek üzere dosyaları yeniden adlandırmak için bulunan dosyalar üzerinde bir kabuk örneği çalıştırıyoruz.

Misal :

$ 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

Uzantıyı (varsa) aşağıdakileri kullanarak koruyan başka bir yol rename:

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

Sonuç beklenen sonuç ise, -nseçeneği kaldırın :

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

renamegreat =) +1
AB

1
Bu abcd'de başarısız olmaz mı? İkinci yakalama grubunu olarak değiştirin (\.?[^\.]+).
ps95

@ prakharsingh95 Bu doğru, ancak (\.?[^\.]+)yalnızca ikinci noktaya kadar eşleşeceği ve ardışık noktalarla dosya adıyla eşleşmeyeceği veya herhangi bir nokta ile bitmeyeceği için doğru değil. Zor bir çözüm değil, tek yol iki oyuncu değişikliği yapıyor.
kos

@kos haklısın. ([^ \.] +). *? ([^ \.] + $) Peki ya iyimserlik konusunda emin değilim. Çalışan keman: regex101.com/r/rQ9lX1/1
ps95

1
@ prakharsingh95 .karakter sınıflarından kaçmak istemiyorsunuz .
terdon

5

Kullanma find:

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

Misal

% 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

Neden -name "*"? Testlerden kalanlar? ;)
kos

1
@kos Eski alışkanlık: \
AB

3

Sadece eğlence için ve kıkırdayarak bir çözüm rename. Değerlendirilen renamekeyfi bir dizeyi kabul eden bir Perl aracı olduğundan, her türlü parlaklığı yapabilirsiniz. İşe yarayan bir çözüm şudur:

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

İlginç fikir +1
AB

2

Komut dosyası, birden çok durumu kapsar: tek nokta ve uzantı (dosya.txt), birden çok nokta ve uzantı (dosya.1.txt), ardışık noktalar (dosya..foobar.txt) ve dosya adındaki noktalar (dosya. Veya dosya..).

Senaryo

#!/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

Komut dosyası iş başında

$./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

Dosyada satır olmadığını unutmayın. ve dosya .., dolayısıyla satır sayısı 0

Komut dosyasını ve önerilen düzenlemeleri gözden geçirdikleri için terdon ve Helio'ya özel teşekkürler


2

@Helio ile sohbette geliştirilen bir başka bash yolu :

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

Bodur bir ikinci baş ( (.*)(\.[^.]+)$) ile garip görünümlü monocled adam sadece uygun uzantıları ( .foodeğil ..) maç gerekir . Herhangi bir uzantı yoksa, BASH_REMATCHdizi boş olacaktır. Dosya adı için varsayılan bir değer ${BASH_REMATCH[1]:-$file}kullanarak ve yalnızca uzantıyı olduğu gibi kullanarak bundan yararlanabiliriz.

Nokta dosyalarını işlemek için terdon ve Heliofind tarafından önerildiği gibi kullanabilirsiniz .

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: Komut için bir açıklama yapamazdım. ;-)
Helio
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.