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
Why Does The Solaris Assembler Generate Different Machine Code Than The Gnu Assembler Here
Reading Serial Port Blocks for Unknown Reason
How to Handle Bash with Multiple Arguments for Multiple Options
Linux X86 Nasm - Subroutine: Print a Dword from Eax
Grep and Sed with Spaces in Filenames
How to Move Old File to Another Folder
Joining Line Breaks in Fasta File with Condition in Sed/Awk/Perl One-Liner
Window Placement: Winsplit Revolution -Like Application for Linux (Kde)
Change The Default Find-Grep Command in Emacs
Why Are There Global Offset Tables and Procedure Linkage Tables in Statically Linked Executables
Kill The Previous Command in a Pipeline
Driver Ch341 Usb Adapter Serial Port or Qserialport Not Works in Linux
Compile Swift Code to Native Executable for Linux
Prevent Usbhid from Autoloading When Usb Hid Device Is Plugged In