1
 files=`find C:/PATH/TO/DIRECTORY -name *.txt`

 for file in $files; do
 #need code to rename $file, by moving it into the same directory

eg. $file was found in C:/PATH/TO/DIRECTORY/2014-05-08. how do I rename $file to back to that directory and not to C:/PATH/TO/DIRECTORY?

john stamos
  • 1,054
  • 5
  • 17
  • 36

3 Answers3

2

You can use -execdir option in find:

find C:/PATH/TO/DIRECTORY -name '*.txt' -execdir mv '{}' '{}'-new \;

As per man find:

-execdir utility [argument ...] ;

The -execdir primary is identical to the -exec primary with the exception that utility will be executed from the directory that holds the current file.

Community
  • 1
  • 1
anubhava
  • 761,203
  • 64
  • 569
  • 643
  • 1
    +1: Nothing in here actively promotes any bad practice. (That said, it might be worth noting that `-execdir` isn't POSIX-specified, so it's possible to have find implementations that don't provide it). – Charles Duffy Jul 03 '14 at 04:43
0
find C:/PATH/TO/DIRECTORY -name \*.txt | while read file
do
   dir=$(dirname "$file")
   base=$(basename "$file")
   mv "$file" "$dir/new_file_name"
done
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • [Parameter expansion](http://mywiki.wooledge.org/BashGuide/Parameters#Parameter_Expansion) would be more efficient... – jasonwryan May 08 '14 at 20:44
  • Omg, you're splitting the result of ``find`` by spaces and then you're iterating over it. Also you have to quote ``"$file"``. Please see other answers. – Aleks-Daniel Jakimenko-A. Jul 02 '14 at 07:00
  • -1: Doesn't work correctly with filenames containing newlines in their names, doesn't work correctly with filenames containing backslash escape sequences. – Charles Duffy Jul 03 '14 at 04:39
  • 1
    If you *must* pipe the output of `find` into `while read`, using `-print0` and `IFS= read -r -d ''` is the Right Thing. – Charles Duffy Jul 03 '14 at 04:40
  • @CharlesDuffy, your comment about file names containing newlines as well as other references to the same subject continues to be a surprise to me. When I write `bash` scripts, I hardly ever think about that possibility. However, others must do such crazy things for it to be a known issue and a pain point for many SO users. I really don't know how to improve my answer to work with such file names. Thanks for your input. – R Sahu Jul 03 '14 at 05:38
0

You would be better served by using this structure:

while read fname
do
  ....
done < <(find ...)

Or, if you're not using bash:

find ... | while read fname
do
  ....
done

The problem with storing the output of find in a variable, or even doing for fname in $(find ...), is with word splitting on whitespace. The above structures still fail if you have a file name with a newline in it, since they assume that you have one file name per line, but they're better than what you have now.

An even better solution would be something like this:

find ... -print0 | xargs -0 -n1 -Ixxx somescript.sh "xxx"

But even that might have issues if filenames have quotes or other things in them.

The bottom line is that parsing arbitrary data (which filenames can be) is hard...

twalberg
  • 59,951
  • 11
  • 89
  • 84
  • 1
    I'd suggest `read -r`, and, if using bash and a `find` with modern extensions (no longer limited to GNU), `IFS= read -r -d ''` and `find ... -print0` – Charles Duffy May 08 '14 at 21:05
  • ...also, what exactly are the potential quoting issues with `xargs -0`? My understanding is that in that mode it passes content entirely literally. – Charles Duffy May 08 '14 at 21:06
  • @CharlesDuffy I may be wrong, but I was imagining issues with the `somescript.sh "xxx"` part if `xxx` gets replaced with something that has especially mis-matched quotes or escape characters or something. I don't think `xargs` would have an issue reading the entries, just that the shell spawned to process each entry might fall down on certain inputs (especially if the script it's calling is carelessly written)... Good points on the other stuff regarding `read -r` and `IFS`, though... – twalberg May 08 '14 at 21:09
  • @twalberg Obviously better than OP's, but [this](http://stackoverflow.com/a/7039579/3076724) has slightly better syntax if you want to be precise about avoiding all possible errors. – Reinstate Monica Please May 08 '14 at 22:08
  • By the way -- the last form you give here *doesn't* have problems with any possible filename at all, including ones with quotes -- a shell doesn't care if an argv entry it was exec'd with has escape characters; it's all just NUL-terminated string data at that point. Might be worth being a little more emphatic about its correctness. – Charles Duffy Jul 03 '14 at 04:41