it-swarm.cn

如何使iconv用转换后的输出替换输入文件?

我有一个bash脚本,该脚本枚举目录中的每个* .php文件,并将iconv应用于该脚本。这将在STDOUT中输出。

由于添加-o参数(根据我的经验)实际上可能在转换发生之前写入了一个空白文件,如何调整脚本以进行转换,然后覆盖输入文件?

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

这是行不通的,因为iconv首先创建了输出文件(由于该文件已经存在,它将被截断),然后开始读取其输入文件(现在为空)。大多数程序都以这种方式运行。

为输出创建一个新的临时文件,然后将其移动到位。

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

如果您平台的iconv没有-o,则可以使用Shell重定向达到相同的效果。

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

Colin Watson的sponge实用程序 (包含在 Joey Hess的moreutils )中使此操作自动化:

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

这个答案不仅适用于iconv,而且适用于任何过滤器程序。值得一提的一些特殊情况:

  • GNU sed和Perl -p 有一个 -i选项来替换文件。
  • 如果文件过大,则过滤器只会修改或删除某些部分,而不会添加任何内容(例如greptrsed 's/long input text/shorter text/'),并且您喜欢危险的生活,您可能希望真正地 在适当位置修改文件 (这里提到的其他解决方案会创建一个新的输出文件并将其移到最后,所以原来的如果命令由于任何原因被中断,数据将保持不变)。
80

替代方法是recode,它使用libiconv库进行某些转换。它的行为是用输出替换输入文件,因此可以正常工作:

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

由于recode接受多个输入文件作为参数,因此可以节省for循环:

recode cp1251..utf8 *.php
61
manatwork

目前

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

奇迹般有效

4
galeksandrp

您可以在Ex模式下使用Vim:

ex -sc '%!iconv -f cp1251 -t utf8' -cx "$file"
  1. %选择所有行

  2. !运行命令

  3. x保存并关闭

1
Steven Penny

一种选择是使用Perl的接口与iconv及其-i模式进行就地编辑:

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

使用GNU awk),您还可以执行以下操作:

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

ksh93 Shell也有>;运算符,用于将输出存储在临时文件中,如果命令成功,则将其重命名为重定向文件:

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

这是一个 简单示例 。它应该为您提供足够的信息以开始使用。

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

为我工作

0
CoNsTaR

您可以使用find,至少这在Raspbian Stretch上对我有用:

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