Mengganti nama file untuk menambahkan akhiran

13

Saya perlu perintah untuk mengganti nama semua file di direktori saat ini bekerja, dengan cara yang nama file baru akan sama dengan yang lama, tetapi termasuk akhiran yang sesuai dengan jumlah baris dari file asli (misalnya jika file tersebut fmemiliki 10 baris maka harus diubah namanya menjadi f_10).

Inilah upaya saya (tidak bekerja):

 linenum=$(wc -l); find * -type f | grep -v sh | rename 's/^/ec/'*
Martin Yeboah
sumber
Anda bisa menjawabnya! (Jika itu menambahkan sesuatu yang baru pada jawaban yang ada - tetapi sepertinya memang demikian)
Volker Siegel

Jawaban:

13

Bagaimana tentang:

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

Sebagai contoh:

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

Jika Anda ingin menyimpan ekstensi (jika ada), gunakan ini sebagai gantinya:

for f in *; do 
    ext=""; 
    [[ $f =~ \. ]] && ext="."${f#*.}; 
    mv "$f" "${f%%.*}"_$(wc -l < "$f")$ext; 
done
terdon
sumber
Terima kasih terdon! baris perintah ini tampaknya menyelesaikan pekerjaan tetapi bagaimana saya bisa mengubah titik (.) menjadi (_)? Juga, karena skrip saya ada di dalam folder, itu juga diganti namanya dan karenanya memungkinkan skrip saya dieksekusi sekali (karena nama skrip berubah ...)
Martin Yeboah
@MartinYeboah lihat jawaban yang diperbarui untuk _. Adapun naskahnya, naskah apa? Itu harus dijalankan dari baris perintah, tidak perlu skrip. Jika Anda hanya ingin mencocokkan beberapa file, ubah in *to, misalnya, in *txtatau sesuatu.
terdon
terima kasih banyak;) Saya benar-benar lupa bahwa itu harus dieksekusi dari baris perintah :)
Martin Yeboah
Saya pikir wc -l < $fbukannya grep akan lebih mudah untuk dipahami (dan mungkin lebih baik untuk melakukan tetapi saya belum memeriksanya).
musiKk
@musiKk ya, tetapi karena jawaban lain menggunakan wc, saya ingin menunjukkan pendekatan yang berbeda. Tapi OK, cukup adil.
terdon
10

Anda dapat mencoba liner yang satu ini:

find . -maxdepth 1 -type f -exec bash -c 'mv -i "$1" "$1.$(wc -l <"$1")"' _ {} \;
  • Ini akan menemukan semua file di direktori kerja saat ini ( find . -maxdepth 1 -type f)

  • Kemudian kami menjalankan contoh shell di atas file yang ditemukan untuk mengubah nama file untuk menambahkan jumlah baris.

Contoh:

$ 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
heemayl
sumber
6

Cara lain yang mempertahankan ekstensi (jika ada) menggunakan rename:

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

Jika hasilnya yang diharapkan, hapus -nopsi:

for f in *; do rename "s/([^.]+)(\.?.*)/\$1_$(< "$f" wc -l)\$2/" "$f"; done
kos
sumber
renamehebat =) +1
AB
1
Bukankah ini gagal pada abcd? Ubah grup tangkapan kedua menjadi (\.?[^\.]+).
ps95
@ prakharsingh95 Itu benar, namun (\.?[^\.]+)tidak ok juga karena akan cocok hanya sampai titik kedua dan tidak akan cocok dengan nama file dengan titik-titik berturut-turut atau berakhir dengan titik terlepas. Ini bukan solusi mudah yang sulit, satu-satunya cara tampaknya melakukan dua pergantian.
kos
@kos kamu benar. Bagaimana dengan ([^ \.] +). *? ([^ \.] + $) Saya tidak yakin dengan optimalitas. Biola yang bekerja: regex101.com/r/rQ9lX1/1
ps95
1
@ prakharsingh95 Anda tidak ingin melarikan diri .di dalam kelas karakter.
terdon
5

Menggunakan find:

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

Contoh

% 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
AB
sumber
Mengapa -name "*"? Sisa dari tes? ;)
kos
1
@kos Kebiasaan lama: \
AB
3

Hanya untuk bersenang-senang dan tertawa dengan solusi rename. Karena renamemerupakan alat Perl yang menerima string arbitrer yang dievaluasi, Anda dapat melakukan segala macam kejahatan. Solusi yang tampaknya berhasil adalah sebagai berikut:

rename 's/.*/open(my $f, "<", $_);my $c=()=<$f>;$_."_".$c/e' *
muskK
sumber
Gagasan menarik +1
AB
2

Script di bawah ini mencakup banyak kasus: titik tunggal dan ekstensi (file.txt), banyak titik dan ekstensi (file.1.txt), titik-titik berturut-turut (file..foobar.txt), dan titik-titik dalam nama file (file. Atau mengajukan..).

Naskah

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

Script sedang beraksi

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

Perhatikan bahwa tidak ada baris dalam file. dan file .., maka jumlah baris adalah 0

Terima kasih khusus kepada terdon dan Helio untuk meninjau naskah dan pengeditan yang disarankan

Sergiy Kolodyazhnyy
sumber
2

Cara lain bash, dikembangkan dengan @Helio dalam obrolan :

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

Pria bermata satu yang terlihat aneh dengan kepala kedua yang terhambat ( (.*)(\.[^.]+)$) harus cocok dengan ekstensi yang tepat ( .foo, bukan ..). Jika tidak ada ekstensi, maka BASH_REMATCHarray akan kosong. Kita dapat memanfaatkan ini dengan menggunakan nilai default untuk nama file ${BASH_REMATCH[1]:-$file}, dan hanya menggunakan ekstensi apa adanya.

Untuk menangani file dot, Anda bisa menggunakan find, seperti yang disarankan oleh terdon dan Helio .

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
muru
sumber
+1: Saya tidak akan bisa melakukan penjelasan untuk perintah. ;-)
Helio