1

I have the following folder structure.

Service
|
-- App1
  |
  --- bin
  |
  --- file1
  |
  --- file2
|
--App2
  |
  --- bin
  |
  --- file1
  |
  --- file2
  |
  --- file3
|
--App3
  |
  --- bin
  |
  --- file1
  |
  --- file2

I'm looking to move files only from the root of App folders to their corresponding bin folders whilst preserving GIT history. So the end result should be:

Service
|
-- App1
  |
  --- bin
     |
      --- file1
     |
      --- file2
|
--App2
  |
  --- bin
     |
      --- file1
     |
      --- file2
     |
      --- file3
|
--App3
  |
  --- bin
     |
      --- file1
     |
      --- file2

I attempted the following...

#!/bin/bash

dir1="/c/Service"

subs=`ls $dir1`

for i in $subs; do
  git mv $dir1/$i/* $dir1/$i/bin/
done

...but see the following errors:

fatal: can not move directory into itself

fatal: Invalid path '/c': No such file or directory

Any help appreciated.

3
  • Path /c:? What operating system are you using?
    – terdon
    Jul 29, 2022 at 16:46
  • So your command runs "git mv /c/Service/App1/* /c/Service/App1/bin" and the "*" will include "bin". You need to get rid of the bin. You could do the move in 2 steps, move first into ElEpHaNt or another name that doesn't exist and then move that to bin. What do you want to do with things already in "bin"?
    – icarus
    Jul 29, 2022 at 16:49
  • The operating system is Windows where I have Git for Windows installed. The "bin" folder is empty for all Apps.
    – Confounder
    Jul 30, 2022 at 20:33

1 Answer 1

0

From the parent of the Service directory, you can do:

$ for file in Service/*/*; do 
    if [[ -f "$file" ]]; then 
        echo mv "$file" "$(dirname -- "$file")/bin"
    fi
 done
mv Service/App1/file1 Service/App1/bin
mv Service/App1/file2 Service/App1/bin
mv Service/App2/file1 Service/App2/bin
mv Service/App2/file2 Service/App2/bin
mv Service/App2/file3 Service/App2/bin
mv Service/App3/file1 Service/App3/bin
mv Service/App3/file2 Service/App3/bin

If that looks correct, remove the echo and run it again to actually move the files.

Note that the approach above will preserve git history, as requested. If you don't want to preserve it but instead you want to add these commands to git's history, simply use git mv instead of mv:

for file in Service/*/*; do 
    if [[ -f "$file" ]]; then 
        echo git mv "$file" "$(dirname -- "$file")/bin"
    fi
 done
7
  • This won't preserve git history
    – cryptarch
    Jan 13, 2023 at 2:42
  • @cryptarch why? I think I haven't understood what is meant by preserving git history. Isn't the history stored in the .git directory? Why would this affect it one way or another?
    – terdon
    Jan 13, 2023 at 10:07
  • The code you've provided merely uses mv, which doesn't register the change in filename with git. That means when checking the git history of the new file, it will be truncated; changes done to the old file won't be associated with the new file. At minimum, the mv command should be prefixed with git (i.e. echo git mv "$file" ..., and at the end of the forloop there should be a git commit to record the change.
    – cryptarch
    Jan 13, 2023 at 17:57
  • @cryptarch yes, exactly, since it doesn't use git, it will not affect git history and, therefore, will preserve it. If we do it your way, we don't preserve the history, we're changing it. If the OP meant what you are suggesting, then that really should be clarified in the question since "preserve" means "do not change". But I added a version that doesn't preserve the history and instead changes it as suggested.
    – terdon
    Jan 13, 2023 at 18:06
  • 1
    Yeah, I mean, frankly your approach makes more sense to me it just isn't how I understood the concept of "preserving" but then I'm a language geek and a pedant so it's probably me :)
    – terdon
    Jan 13, 2023 at 18:14

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .