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


70

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

Vì việc thêm -otham 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

Câu trả lời:


76

Điều này không hoạt động vì iconvtrướ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 iconvbạn 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

spongeTiện ích của Colin Watson (bao gồm trong nhiều hơn Joey Hess ) tự động hóa điều 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 iconvcho 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 -pcó một -itùy chọn để thay thế các tệp tại chỗ.
  • Nếu tập tin của bạn là vô cùng lớn, bộ lọc của bạn chỉ được sửa đổi hoặc loại bỏ một số bộ phận nhưng không bao giờ thêm điều (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ự thay đổi các tập tin tại chỗ (các giải pháp khác được đề cập ở đây tạo ra một tập tin đầu ra mới và di chuyển nó vào vị trí ở cuối, vì vậy dữ liệu gốc không thay đổi nếu lệnh bị gián đoạn vì bất kỳ lý do nào).

3
Tôi không chắc chắn liệu quyền tác giả có spongenên được quy cho riêng Joey Hess hay không; đó là gói moreutilsbao gồm spongenhững gì anh ta duy trì, nhưng liên quan đến nguồn gốc của sponge, bằng cách theo các liên kết từ trang chủ của moreutils, tôi đã tìm thấy nó ban đầu được đăng và đề nghị đưa vào bởi Colin Watson: "Joey viết về việc thiếu công cụ mới mà phù hợp với triết lý Unix. Yêu thích của tôi về những điều như vậy tôi đã viết là sponge"(Thứ Hai, 06 tháng 2 năm 2006).
imz - Ivan Zakharyaschev

3
Tôi sử dụng Mac OS, không có tùy chọn -o trong iconv, tôi phải thay đổi `iconv -f cp1251 -t utf8 -o" $ file.new "" $ file "` thànhiconv -f cp1251 -t utf8 "$file" > "$file.new"
code4j

Một số lệnh, như sort, khá thông minh liên quan đến -otham số và nếu chúng phát hiện tệp đầu ra giống như đầu vào, chúng sẽ quản lý nội bộ một tệp tạm thời để nó chỉ hoạt động.
jesjimher

56

Một cách khác 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

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

recode cp1251..utf8 *.php

2
Cảm ơn, điều này xứng đáng nâng cao hơn. Chỉ cần tự hỏi nơi được nhìn chằm chằm trong sách hướng dẫn về 2 dấu chấm giữa các bảng mã ...
neurino

2
CÂU HỎI THƯỜNG GẶP thường trông giống TRƯỚC KHI..CÁC, với TRƯỚC và SAU là các ký tự. Một lời khuyên: hãy thử info recodethay thế. Là dài dòng hơn.
manatwork

4

Để bây giờ

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

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


5
Lúc đầu, tôi thực sự nghĩ rằng nó hoạt động. Nhưng có vẻ như đầu ra vượt quá 32K bị cắt và với đầu vào thậm chí nhiều hơn, nó kích hoạt các kết xuất lõi.
x-yuri

1

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


0

Đâ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.....: dede.exe@gmail.com
#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
echo "`iconv -f cp1251 -t utf8 $file`" > "$file"

làm việc cho tôi


0

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

Một tùy chọn là sử dụng perlgiao diện iconv-ichế độ của nó để 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

Các ksh93vỏ cũng có một >;nhà điều hành cho rằng có thể lưu được đầu ra trong một tập tin tạm thời được đổi tên thành file 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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.