Alexander Torstling
Alexander Torstling

Reputation: 18898

xargs: variable substitution after redirection

I'm trying to find all text files which have the encoding iso-8859-1 and convert these to UTF-8. My attempt so far is:

find . -name '*.txt' | xargs grep 'iso-8859-1' | cut -d ':' -f1 | 
xargs iconv -f ISO-8859-1 -t UTF-8 {} > {}.converted

The (obvious) problem is that the last variable substitution won't work, since {} occurs after the redirection, and doesn't belong to xargs. As is I only get one file called {}.converted, not a.txt.converted, b.txt.converted etc. How can I make this work?

Note: I'm doing this on Cygwin, where iconv doesn't seem to support -o.

Upvotes: 6

Views: 3836

Answers (5)

Ihe Onwuka
Ihe Onwuka

Reputation: 477

echo the command you want xargs to operate on to a string that is piped to the shell and that will overcome the substitution problem.

find . -name '*.txt' | xargs grep 'iso-8859-1' | cut -d ':' -f1 | 
xargs echo "iconv -f ISO-8859-1 -t UTF-8 {} > {}.converted" | bash

Upvotes: 0

Ole Tange
Ole Tange

Reputation: 33685

If you have GNU Parallel http://www.gnu.org/software/parallel/ installed you can do this:

find . -name '*.txt' | parallel grep -il iso-8859-1 | parallel iconv -f ISO-8859-1 -t UTF-8 {} \> {}.converted

You can install GNU Parallel simply by:

wget http://git.savannah.gnu.org/cgit/parallel.git/plain/src/parallel
chmod 755 parallel
cp parallel sem

Watch the intro videos for GNU Parallel to learn more: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

Upvotes: 3

choroba
choroba

Reputation: 241858

You are almost there:

find . -name '*.txt' | xargs grep -i iso-8859-1 | cut -f1 -d: | \
xargs -I% echo iconv -f l1 -t utf8 % \> %.utf | bash

Upvotes: 0

glenn jackman
glenn jackman

Reputation: 246807

Assuming none of your files have newline characters in the name, and assuming you have GNU find and xargs::

find . -name '*.txt' -print0 |
xargs -0 grep -l 'iso-8859-1' |
while read -r file; do
    iconv -f ISO-8859-1 -t UTF-8 "$file" > "$file".converted 
done

With grep -l, you don't need the cut command in the pipeline.

Upvotes: 1

e.dan
e.dan

Reputation: 7475

How about a for loop like:

for file in `find . -name '*.txt' | xargs grep 'iso-8859-1' | cut -d ':' -f1`; do
    iconv -f ISO-8859-1 -t UTF-8 $file > $file.converted
done

Upvotes: 2

Related Questions