Reputation: 3327
Any idea why this command is not working? btw, I'm trying to strip out the extensions of all csv files in current directory.
find -type f -iname "*.csv" -exec mv {} $(basename {} ".csv") \;
Tried many variants including the parameter expansions, xargs ... Even then all went futile.
Upvotes: 6
Views: 5011
Reputation: 1242
This should do:
find ./ -type f -iname "*.csv" -exec sh -c 'mv {} $(basename {} .csv)' \;
find
is able to substitute {}
with its findings since the quotes prevent executing the subshell until find
is done. Then it executes the -exec
part.
The problem why yours is not working is that $(basename {} ".csv")
is executed in a subshell (-> $()
) and evaluated beforehand. If we look at the command execution step-by-step you will see what happens:
find -type f -iname "*.csv" -exec mv {} $(basename {} ".csv") \;
- your commandfind -type f -iname "*.csv" -exec mv {} {} \;
- subshell gets evaluated ($(basename {} ".csv")
returns {}
since it interprets {}
as a literal)find -type f -iname "*.csv" -exec mv {} {} \;
- as you see now: move does actually nothingUpvotes: 10
Reputation: 3716
First, take care that you have no subdirectories; find
, without extra arguments, will automatically recur into any directory below.
Simple approach: if you have a small enough number of files, just use the glob (*) operator, and take advantage of rename:
$ rename 's/.csv$//' *.csv
If you have too many files, use find
, and perhaps xargs
:
$ find . -maxdepth 1 -type f -name "*.csv" | xargs rename 's/.csv$//'
If you want to be really safe, tell find
and xargs
to delimit with null-bytes, so that you don't have weird filenames (e.g., with spaces or newlines) mess up the process:
$ find . -maxdepth 1 -type f -name "*.csv" -print0 | xargs -0 rename 's/.csv$//'
Upvotes: 2