find, xargs and mv: renaming files with double-quotes, expansion and bash precedence issue
Solution 1
Assuming you have the rename
command installed, use:
find . -name '*"*' -exec rename 's/"//g' {} +
The rename
command takes a Perl
expression to produce the new name. s/"//g
performs a global substitution of the name, replacing all the quotes with an empty string.
To do it with mv
you need to pipe to a shell command, so you can execute subcommands:
find . -name '*"*' -exec sh -c 'mv "$0" "$(printf %s "$0" | tr -d "\"")"' {} \;
What you wrote pipes the output of xargs
to tr
, it doesn't use tr
to form the argument to mv
.
Solution 2
xargs -0 -I {} mv {} {} | tr -d \"
doesn't make sense: mv
doesn't produce output. Thus you cannot build pipelines with mv
.
find . -name '*"*' -exec bash -c 'mv "$1" "${1//\"/}"' bash {} \;
or with less overhead
find . -name '*"*' -exec bash -c 'for file in "$@"; do mv "$file" "${file//\"/}"; done' bash {} +
Solution 3
You might do...
mkdir ../_cp
pax -Xwrl -s'/"//gp' . "${PWD%/*}/_cp"
That just creates a bunch of hardlinks to all files in the hierarchy rooted at .
in ../_cp
. You can then verify everything is well with both directories before removing one of them - they are pretty much the same directories after all, except in one directory there are no filenames which contain a "
.
Related videos on Youtube
Harv
Updated on September 18, 2022Comments
-
Harv over 1 year
Ok, I'm simply trying to strip out double-quotes in my filenames. Here's the command I came up with (bash).
$ find . -iname "*\"*" -print0 | xargs -0 -I {} mv {} {} | tr -d \"
The problem is the
'mv {} {} | tr -d \"'
part. I think it's a precedence problem: bash seems to be interpreting as(mv {} {}) | tr -d \")
, and what I'm left with are both filenames stripped of double-quotes. That's not what I want, obviously, because then it fails to rename the file. Instead, I want the first filename to have the quotes, and the second not to, more like this:mv {} ({} | tr -d \")
.How do I accomplish this? I've tried brackets and curly braces, but I'm not really sure what I'm doing when it comes to explicitly setting command execution precedence.
-
Barmar over 9 yearsDoes your system have the
rename
command that uses regular expressions to rename by patterns? -
Harv over 9 years@Barmar no, but it looks like I could grab a copy using homebrew - rename version 1.6 from plasmasturm.org/code/rename. Is that what you're referring to?
-
Barmar over 9 yearsYes, that's it.
-
-
Harv over 9 yearsThat worked. Can you expand your answer to explain why, and if it's possible to do this without rename?
-
Harv over 9 yearsAha, cool. That helps me understand why it didn't work, thanks.