3

I'm trying to do a number of test runs on an algorithm and as such have a number of directories containing exactly the same data (subdirectories and files) to be run on a cluster. I would like all of these directories to contain a file called randomseed.txt which contains a unique integer. Currently, the randomseed files exist, but contain the same integer: 1. Is there a bash script I could use, or a variation of find that I could use to achieve this simply?

My idea was something like this:

#!/bin/bash

declare -i VAR
VAR=1

find . -type f -name "randomseed.txt" -execdir VAR=$VAR+1 | $VAR > randomseed.txt \;

echo $VAR
echo done

but I'm not entirely sure how or if I can do something like this with -exec or -execdir.

4

This should work for you:

/bin/bash
x=1
find . -name 'randomseed.txt' | \
while IFS= read file ; do
  echo $x > "$file"
  x=$(($x+1))
done

IFS= is to prevent breaking on spaces in file path if they exist, probably will not happen in your case.

Piping results of find into the while loop read which assigns the value to file then runs loop body. x=$(($x+1)) is your gross x+=1

  • 4
    You should quote $file, since that would break with spaces, other special characters, etc. – muru Mar 21 '17 at 7:40
3

Run a loop creating numbers and have the find-executed command read those numbers:

for ((i = 1; ; i++)); do echo $i; done | 
  find . -type f -name "randomseed.txt" -exec sh -c 'read i; echo $i > "$1"' _ {} \;

You can also use seq:

seq 1 inf | find . -type f -name "randomseed.txt" -exec sh -c 'read i; echo $i > "$1"' _ {} \;
  • I ended up using a variation of this to change directory names in a similar way! Thanks for the lead, though it wasn't what your answer was originally intended for! – onyinyang Mar 22 '17 at 19:13
3

Instead of using find, you could turn on globstar to make shell globbing recursive.

 shopt -s globstar

cd to the parent directory of this structure, then to test (over)writing the files:

n=0; for i in **; do [[ -d "$i" ]] && echo "echo $((++n)) >" "$i"/randomseed.txt; done

You can see it's going to write a file in each directory at every level. You can then remove the extra echo to actually write the files:

n=0; for i in **; do [[ -d "$i" ]] && echo $((++n)) > "$i"/randomseed.txt; done

You might want to unset globstar when done:

shopt -u globstar
  • The only problem with this for me is that randomseed.txt exists (with other directories) at a depth of 2 and I don't want randomseeds in all the other directories (it wouldn't actually effect anything but would be extra junk). I just edited your script to point to the specific directory where the randomseed.txt is within the structure and this worked great! I also didn't need to use globstar for this instance. Thanks! – onyinyang Mar 21 '17 at 15:44
  • 1
    @onyinyang oh I see - I couldn't tell that from your description :) It was a pleasure, thanks for asking a nice question :) – Zanna Mar 21 '17 at 15:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.