I need to search (on the whole disk) and replace (where there are matches) one file with another (both in the same path).


  Folder 1
    x*.txt (good) (e.g.: xFile.txt)
    *.txt (bad) (e.g.: File.txt)

If there is a match of both files in the same path, i need to delete: *.txt (e.g.: File.txt) and rename: x*.txt (e.g.: xFile.txt) to *.txt (e.g.: File.txt)


 Folder 1
  *.txt (e.g: File.txt... old xFile.txt)

I use this command:

find -name 'x*.txt' | sed -r 'p;s/g([^\/]*.txt)/\1/' | xargs -d '\n' -n2 mv

The problem is that the command does not verify if both files exist (xFile.txt and File.txt in the same path) before executing the order

How can I solve it? Thanks in advance

  • 1
    find xfile.txt, and check [[ -f "${file#x}" ]] (which strips a leading x from the found file and checks to see if that file is present. If present, then do your switcheroo. – DopeGhoti Jun 13 '18 at 17:25
  • 1
    Alternatively, find file.txt and check [[ -f x"$file" ]]. If the replacement is there, do your switcheroo. – DopeGhoti Jun 13 '18 at 17:26
  • @DopeGhoti Can you explain this with a single command line? – ajcg Jun 13 '18 at 19:28
  • What if there's a xx1.txt, x1.txt and 1.txt? – Stéphane Chazelas Jun 13 '18 at 20:56

With GNU tools, you could do something like:

(export LC_ALL=C
  find . -name '*.txt' -print0 |
  sed -Ez 's|/x([^/]*)$|/\1|' |
  sort -z |
  uniq -zd |
  sed -z 'h;s|.*/|&x|;G' |
  xargs -r0n2 echo mv)

That assumes there are not files whose name starts with more than one x. For instance, it won't do mv ./xx.txt ./x.txt


First, we define a function to do the work for us:

switcheroo() {
    [[ -f x"$1" ]] && mv -f x"$1" "$1"
export -f switcheroo

Now, we use find and some black magic to iterate over our foundlings:

find . -name \*.txt -execdir bash -c 'switcheroo "$0"' "{}" \;

We use find to locate all files with a .txt extension (this can be refined to suit whatever criteria you like) and in turn run them through the switcheroo process -- we use [[ ... ]] to test for the existence of the replacement file, and if it is present, use mv to effect the replacement.

  • I don't think find can run a shell function (but it's simple enough to just put inline) – ilkkachu Jun 13 '18 at 19:48
  • Yeah, you do need to use -execdir sh '[ -f "x$1" ] && mv "x$1" "$1"' sh {} \; – ilkkachu Jun 13 '18 at 20:01
  • Nop. syntax error – ajcg Jun 13 '18 at 20:14
  • @DopeGhoti Your command does not solve my problem, described in the question. Thanks anyway – ajcg Jun 13 '18 at 20:28
  • Could you explain how this does not do what you are asking after? – DopeGhoti Jun 13 '18 at 21:06

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.