Xargs and Find, Rm Complaining About \N (Newline) in Filename

xargs and find, rm complaining about \n (newline) in filename

The ls appends a newline and the last xargs -0 says the newline is part of the file name.
Run the last xargs with -d '\n' instead of -0.

BTW, due to the way xargs works, your whole pipe is a bug waiting to happen. Consider a really long file name list produced by the find, so that the xargs -0 ls runs ls multiple times with subsets of the filenames. Only the oldest of the last ls invocation will make it past the tail -1. If the oldest file is actually, say, the very first filename output by find, you are deleting a younger file.

Recursively rename files using find and sed

This happens because sed receives the string {} as input, as can be verified with:

find . -exec echo `echo "{}" | sed 's/./foo/g'` \;

which prints foofoo for each file in the directory, recursively. The reason for this behavior is that the pipeline is executed once, by the shell, when it expands the entire command.

There is no way of quoting the sed pipeline in such a way that find will execute it for every file, since find doesn't execute commands via the shell and has no notion of pipelines or backquotes. The GNU findutils manual explains how to perform a similar task by putting the pipeline in a separate shell script:

#!/bin/sh
echo "$1" | sed 's/_test.rb$/_spec.rb/'

(There may be some perverse way of using sh -c and a ton of quotes to do all this in one command, but I'm not going to try.)

Make xargs handle filenames that contain spaces

The xargs command takes white space characters (tabs, spaces, new lines) as delimiters.

You can narrow it down only for the new line characters ('\n') with -d option like this:

ls *.mp3 | xargs -d '\n' mplayer

It works only with GNU xargs.

For MacOS:

ls *.mp3 | tr \\n \\0 | xargs -0 mplayer

The more simplistic and practically useful approach (when don't need to process the filenames further):

mplayer *.mp3

Add a newline only if it doesn't exist

Since it removes newline if it's not there, you could simply use:

echo "" >> file;  sed -ie '/^$/d;$G' file; sed -ie '/^$/d;$G' file

Adds a newline and removes everything then adds newline. Not the elegant way, but certainly works :)

Using find, grep and sed together

your find command with the missing argument is very close to working. try:

find / -maxdepth 1 -xdev -type f -exec grep -i "stringtofind" -l {} \; -exec sed -i '/./d' {} \;

you just need to add a backslash escaped semi-colon to the end of each -exec action and add {} to let it know where to substitute the filename.

How can I avoid no input files error from sed, when run from xargs?

If you want to avoid running sed when grep produces no output, then (since you've tagged this with Ubuntu), you can give the -r or --no-run-if-empty argument to xargs:

--no-run-if-empty

-r

If the standard input does not contain any nonblanks, do not run the command. Normally, the command is run once even if there is no input. This option is a GNU extension.

So your command should look like:

grep -rlZ "$old" /etc | xargs -0 -r sed -i "s/$old/$new/g"

(I added grep -Z and xargs -0 flags, since these are supported on your platform, and they make the commands more robust to malicious filenames)


For platforms without xargs -r, then the usual solution is to pass /dev/null as a first filename argument:

grep -rl "$old" /etc | xargs sed -i "s/$old/$new/g" /dev/null

In this case, when there are no matches, sed will operate harmlessly on the null device.

Find and replace text on multiple files

Had to run the command logged in as root because sed -i creates temporary files in /tmp and needed write access.

Thanks:Used jim's syntax with the semicolons which worked fine. ooga, I did not have to escape the literal periods.



Related Topics



Leave a reply



Submit