Unix: Files with spaces and quotes, using xargs

"Please leave a message at the beep, we will get back to you when your support contract expires."

Moderators: phlip, Moderators General, Prelates

Keybounce
Posts: 101
Joined: Fri May 29, 2009 1:41 am UTC

Unix: Files with spaces and quotes, using xargs

Postby Keybounce » Tue Jul 20, 2010 1:04 am UTC

I need some help.

I have a directory that has these files:

Code: Select all

michael$ /bin/ls -1t | tail +14
backup of stbmac
ibook backup bundle
windows backup hfs bundle
windows vmware
kleiman ibook backups
stbmac mini backups
time machine drive
stbmac backups
mac backups
surplus mac stuff-1
kleiman ibook backup-1
leila winxp-1
global time machine
win backup
image 3
image 1
image 2
benjamin's public folder
michael$


All of those are "out of date".

So, I try to clean them up (ignore the permission denied, this is in "test" mode):

Code: Select all

michael$ /bin/ls -1t | tail +14 | xargs -I %  mv % old
mv: rename backup of stbmac to old/backup of stbmac: Permission denied
mv: rename ibook backup bundle to old/ibook backup bundle: Permission denied
mv: rename windows backup hfs bundle to old/windows backup hfs bundle: Permission denied
mv: rename windows vmware to old/windows vmware: Permission denied
mv: rename kleiman ibook backups to old/kleiman ibook backups: Permission denied
mv: rename stbmac mini backups to old/stbmac mini backups: Permission denied
mv: rename time machine drive to old/time machine drive: Permission denied
mv: rename stbmac backups to old/stbmac backups: Permission denied
mv: rename mac backups to old/mac backups: Permission denied
mv: rename surplus mac stuff-1 to old/surplus mac stuff-1: Permission denied
mv: rename kleiman ibook backup-1 to old/kleiman ibook backup-1: Permission denied
mv: rename leila winxp-1 to old/leila winxp-1: Permission denied
mv: rename global time machine to old/global time machine: Permission denied
mv: rename win backup to old/win backup: Permission denied
mv: rename image 3 to old/image 3: Permission denied
mv: rename image 1 to old/image 1: Permission denied
mv: rename image 2 to old/image 2: Permission denied
xargs: unterminated quote


Notice how the quote in the last file name kills xargs?

Here's the problem: I want to work with files with very odd names. (Maybe I'll start a "Danny Directory" project to hold horrendous filenames designed to kill shell scripts?).

My first idea was just mv `...` old, but that turned every separate word into a separate argument, losing all filename spacing.
My second was xargs, which is smart enough to deal with spaces, but not smart enough to deal with quotes (and using "-L 1" didn't help either -- same error).

I don't know of a third, short of learning perl.

So what's a good way to script this?

(Yea, my "workaround" is to use the Gui, and drag; I'd really like to add to my admin toolkit.)
<this space on hold>

User avatar
phlip
Restorer of Worlds
Posts: 7550
Joined: Sat Sep 23, 2006 3:56 am UTC
Location: Australia
Contact:

Re: Unix: Files with spaces and quotes, using xargs

Postby phlip » Tue Jul 20, 2010 1:55 am UTC

You can pass -d '\n' to xargs, which makes it simply use a specified delimeter and not do any of the quote- or backslash-handling. It'll still fail if any filename has a newline in it, but it sounds like that's not the case for you.

A cleaner and more reliable option is to use tools which can give you the list of files as a NUL-separated list... since that's safe regardless of what's in the filenames (since NUL characters aren't possible in filenames). For example:

Code: Select all

find . -maxdepth 1 -mtime +30 -print0 | xargs -0 mv -t old
which will move everything in the current dir that's at least 30 days old into the "old" dir (the -t option to mv makes it so the filenames can be added to the end of the command, like xargs does by default... "mv a b" is the same as "mv -t b a").

Code: Select all

enum ಠ_ಠ {°□°╰=1, °Д°╰, ಠ益ಠ╰};
void ┻━┻︵​╰(ಠ_ಠ ⚠) {exit((int)⚠);}
[he/him/his]

Keybounce
Posts: 101
Joined: Fri May 29, 2009 1:41 am UTC

Re: Unix: Files with spaces and quotes, using xargs

Postby Keybounce » Tue Jul 20, 2010 6:09 am UTC

Thank you.

Although, for me, I'd have used ( ! -newer filename ) instead of -mtime. But yea, that works -- and I thought of find, but didn't think of that for getting the older files.
<this space on hold>

Keybounce
Posts: 101
Joined: Fri May 29, 2009 1:41 am UTC

Re: Unix: Files with spaces and quotes, using xargs

Postby Keybounce » Tue Jul 20, 2010 6:13 am UTC

Bummer -- Mac os x 10.5.8, mv does not take -t, and xargs does not take -d.
<this space on hold>

User avatar
hotaru
Posts: 1040
Joined: Fri Apr 13, 2007 6:54 pm UTC

Re: Unix: Files with spaces and quotes, using xargs

Postby hotaru » Tue Jul 20, 2010 7:20 am UTC

Keybounce wrote:Bummer -- Mac os x 10.5.8, mv does not take -t, and xargs does not take -d.

Code: Select all

find . -maxdepth 1 -mtime +30 -print0 | xargs -0 -Jfiles mv files old

Code: Select all

factorial product enumFromTo 1
isPrime n 
factorial (1) `mod== 1

User avatar
tendays
Posts: 957
Joined: Sat Feb 17, 2007 6:21 pm UTC
Location: HCMC

Re: Unix: Files with spaces and quotes, using xargs

Postby tendays » Tue Jul 20, 2010 2:04 pm UTC

Using while and read also works (I tested with zsh and bash, with filenames containing single and double quotes, and spaces)

Code: Select all

... | while read x ; do mv "$x" old ; done

By the way -1 is implicit in ls if you're piping it into another command.

(EDIT: This will fail if filenames contain newlines, in that case find+xargs with \0-separated names is probably the only reasonable way?)
<Will> s/hate/love/
Hammer wrote:We are only mildly modly. :D
Beware of the shrolymerase!


Return to “The Help Desk”

Who is online

Users browsing this forum: No registered users and 4 guests