it-swarm-vi.com

Làm cách nào để tạo iconv thay thế tệp đầu vào bằng đầu ra được chuyển đổi?

Tôi có một tập lệnh bash liệt kê qua mọi tệp * .php trong một thư mục và áp dụng iconv cho nó. Điều này nhận được đầu ra trong STDOUT.

Kể từ khi thêm -o tham số (theo kinh nghiệm của tôi) thực sự ghi một tệp trống có thể trước khi chuyển đổi diễn ra, làm cách nào tôi có thể điều chỉnh tập lệnh của mình để nó thực hiện chuyển đổi, sau đó ghi đè lên tệp đầu vào?

for file in *.php
do
    iconv -f cp1251 -t utf8 "$file"
done
73
meder omuraliev

Điều này không hoạt động vì iconv trước tiên tạo tệp đầu ra (vì tệp đã tồn tại, nó cắt ngắn nó), sau đó bắt đầu đọc tệp đầu vào của nó (hiện đang trống). Hầu hết các chương trình hành xử theo cách này.

Tạo một tệp mới, tạm thời cho đầu ra, sau đó di chuyển nó vào vị trí.

for file in *.php
do
    iconv -f cp1251 -t utf8 -o "$file.new" "$file" &&
    mv -f "$file.new" "$file"
done

Nếu nền tảng của bạn là iconv không có -o, bạn có thể sử dụng chuyển hướng Shell cho cùng hiệu ứng.

for file in *.php
do
    iconv -f cp1251 -t utf8 "$file" >"$file.new" &&
    mv -f "$file.new" "$file"
done

Tiện ích sponge của Colin Watson (được bao gồm trong Joey Hess's moreutils ) tự động hóa việc này:

for file in *.php
do
    iconv -f cp1251 -t utf8 "$file" | sponge "$file"
done

Câu trả lời này không chỉ áp dụng cho iconv mà còn cho bất kỳ chương trình lọc nào. Một vài trường hợp đặc biệt đáng nói:

  • GNU sed và Perl -p có một -i tùy chọn để thay thế các tập tin tại chỗ.
  • Nếu tệp của bạn quá lớn, bộ lọc của bạn chỉ sửa đổi hoặc xóa một số phần nhưng không bao giờ thêm các thứ (ví dụ: grep, tr, sed 's/long input text/shorter text/') và bạn thích sống một cách nguy hiểm, bạn có thể muốn thực sự sửa đổi tệp tại chỗ (các giải pháp khác được đề cập ở đây tạo một tệp đầu ra mới và di chuyển nó vào vị trí cuối cùng, vì vậy bản gốc dữ liệu không thay đổi nếu lệnh bị gián đoạn vì bất kỳ lý do nào).

Một thay thế là recode, sử dụng thư viện libiconv cho một số chuyển đổi. Hành vi của nó là thay thế tệp đầu vào bằng đầu ra, vì vậy điều này sẽ hoạt động:

for file in *.php
do
    recode cp1251..utf8 "$file"
done

recode chấp nhận nhiều tệp đầu vào làm tham số, bạn có thể sử dụng vòng lặp for:

recode cp1251..utf8 *.php
61
manatwork

Để bây giờ

find . -name '*.php' -exec iconv -f CP1251 -t UTF-8 {} -o {} \;

hoạt động như một lá bùa

4
galeksandrp

Bạn có thể sử dụng Vim trong chế độ Ex:

ex -sc '%!iconv -f cp1251 -t utf8' -cx "$file"
  1. % chọn tất cả các dòng

  2. ! chạy lệnh

  3. x lưu và đóng

1
Steven Penny

Một tùy chọn là sử dụng giao diện của Perl để iconv và chế độ -i Để chỉnh sửa tại chỗ:

Perl -MText::Iconv -i -pe '
  BEGIN{$i=Text::Iconv->new(qw(cp1252 UTF-8));$i->raise_error(1)}
  $_ = $i->convert($_)' ./*.php

Với GNU awk, bạn cũng có thể làm một cái gì đó như:

gawk -v cmd='iconv -f cp1252 -t utf-8' -i inplace '
  {print | cmd}; ENDFILE {close(cmd)}' ./*.php

Shell ksh93 Cũng có toán tử >; Để lưu trữ đầu ra trong tệp tạm thời được đổi tên thành tệp được chuyển hướng nếu lệnh thành công:

for f in *.php; do
  iconv -f cp1252 -t utf-8 < $f >; $f
done
0
Stéphane Chazelas

Đây là một ví dụ đơn giản . Nó sẽ cung cấp cho bạn một thông tin đủ để bắt đầu.

#!/bin/bash
#conversor.sh
#Author.....: dede.exe
#E-mail.....: [email protected]
#Description: Convert all files to a another format
#             It's not a safe way to do it...
#             Just a desperate script to save my life...
#             Use it such a last resort...

to_format="utf8"
file_pattern="*.Java"

files=`find . -name "${file_pattern}"`

echo "==================== CONVERTING ===================="

#Try convert all files in the structure
for file_name in ${files}
do
        #Get file format
        file_format=`file $file_name --mime-encoding | cut -d":" -f2 | sed -e 's/ //g'`

        if [ $file_format != $to_format ]; then

                file_tmp="${unit_file}.tmp"

                #Rename the file to a temporary file
                mv $file_name $file_tmp

                #Create a new file with a new format.
                iconv -f $file_format -t $to_format $file_tmp > $file_name

                #Remove the temporary file
                rm $file_tmp

                echo "File Name...: $file_name"
                echo "From Format.: $file_format"
                echo "To Format...: $to_format"
                echo "---------------------------------------------------"

        fi
done;
0
dede.exe
echo "`iconv -f cp1251 -t utf8 $file`" > "$file"

làm việc cho tôi

0
CoNsTaR

Bạn có thể sử dụng find, ít nhất điều này hiệu quả với tôi trên Raspbian Stretch:

find . -type f -name '*php' -execdir iconv -f cp1251 -t UTF-8 '{}' -o '{}'.tmp \; -execdir mv '{}'.tmp '{}' \;
0
rannala