Đ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 iconv
bạ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
sponge
Tiệ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 iconv
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 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).