Pertanyaan Mengganti nama file untuk menambahkan akhiran


Saya memerlukan perintah untuk mengganti nama semua file di direktori kerja saat ini, dengan cara nama file yang baru akan sama dengan yang lama, tetapi menyertakan akhiran yang sesuai dengan jumlah baris file asli (misalnya jika file tersebut f memiliki 10 baris maka harus diganti namanya menjadi f_10).

Inilah usaha saya (tidak bekerja):

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

12
2018-06-24 14:34


asal


Anda bisa membuat jawabannya! (Jika itu menambahkan sesuatu yang baru pada jawaban yang ada - tetapi sepertinya memang demikian) - Volker Siegel


Jawaban:


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 mempertahankan ekstensi (jika ada), gunakan ini sebagai gantinya:

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

13
2018-06-24 15:58



Terima kasih, terdon! baris perintah ini tampaknya menyelesaikan pekerjaan tetapi bagaimana saya bisa mengubah titik (.) ke (_)? 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 terupdate untuk _. Adapun naskahnya, skrip apa? Itu harus dijalankan dari baris perintah, tidak perlu untuk skrip. Jika Anda hanya ingin mencocokkan beberapa file, ubah in * untuk, misalnya, in *txt atau sesuatu. - terdon♦
terima kasih banyak;) Saya benar-benar lupa bahwa itu harus dijalankan dari baris perintah :) - Martin Yeboah
kupikir wc -l < $f bukannya grep akan lebih mudah dipahami (dan mungkin lebih baik untuk melakukan tetapi saya belum memeriksa itu). - musiKk
@musiKk ya, tapi karena jawaban yang lain sedang digunakan wcSaya ingin menunjukkan pendekatan yang berbeda. Tapi oke, cukup adil. - terdon♦


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)

  • Lalu kita menjalankan contoh shell di atas file yang ditemukan untuk mengganti 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

10
2018-06-24 14:46





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 adalah yang diharapkan, hapus -n pilihan:

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

6
2018-06-24 16:14



renamehebat =) +1 - A.B.
Bukankah ini gagal pada a.b.c.d? Ubah grup tangkapan kedua menjadi (\.?[^\.]+). - ps95
@ prakharsingh95 Itu benar, bagaimanapun (\.?[^\.]+) tidak ok karena akan cocok hanya hingga 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 Anda benar. Bagaimana dengan ([^ \.] +). *? ([^ \.] + $) Saya tidak yakin tentang optimalitas. Biola bekerja: regex101.com/r/rQ9lX1/1 - ps95
@ prakharsingh95 Anda tidak ingin melarikan diri . di dalam kelas karakter. - terdon♦


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

5
2018-06-24 16:14



Mengapa -name "*"? Sisa dari tes? ;) - kos
@kos Kebiasaan lama: \ - A.B.


Hanya untuk bersenang-senang dan tertawa dengan solusi rename. Sejak rename adalah alat Perl yang menerima string acak yang eval'd, Anda dapat melakukan segala macam shenanigans. Solusi yang tampaknya berfungsi adalah sebagai berikut:

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

3
2018-06-25 11:45



Ide menarik +1 - A.B.


Script di bawah ini mencakup beberapa kasus: dot tunggal dan ekstensi (file.txt), beberapa titik dan ekstensi (file.1.txt), titik-titik berurutan (file..foobar.txt), dan titik-titik dalam namafile (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 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 skrip dan pengeditan yang disarankan


2
2018-06-24 21:22





Cara bash lainnya, 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

Orang bermata aneh yang tampak aneh dengan kepala kedua yang terhambat ((.*)(\.[^.]+)$) hanya harus mencocokkan ekstensi yang tepat (.footidak ..). Jika tidak ada ekstensi, maka BASH_REMATCH larik akan kosong. Kita dapat memanfaatkan ini dengan menggunakan nilai default untuk nama file ${BASH_REMATCH[1]:-$file}, dan hanya menggunakan ekstensi seperti 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

2
2018-06-27 01:27



+1: Saya tidak akan bisa melakukan penjelasan untuk perintah. ;-) - Helio