recreate folder structure Osx - macos

I currently have a set of folders that I need to duplicate the structure into another folder.
I currently work with photos that are dumped into a Dump folder in groups.
Eg.
Photo Dump
Group1
Group2 etc
I would like to have a script to recreate these folders without the files to the good folder so that I don't have to recreate them manually
Any ideas?
Nathan

If I understand correctly, you want to copy the parent folder and all of its subfolders, but none of the files contained therein. There might be a simpler way, but I just threw together this Terminal command (which should also work on Linux or anywhere else with Bash):
ls -R | grep :$ | sed 's/\.\/\(.*\):$/\1/' | \
while read thisFolder; do mkdir -p "destination"/"$thisFolder"; done
It will copy the folder structure of all folders in the current directory into a folder called "destination"; you can of course change this to any path you wish, e.g. ~/Desktop/"Folder Copies" or whatever.
Take care to first "cd" into whatever directory contains the folder tree you want to duplicate, because if you run it as soon as you open the terminal, you'll wind up with a replication of your entire home folder directory structure, including the many contained within Library.

I found this to be a tad clearer:
find 'Photo Dump' -type d | sed -e 's:^Photo Dump:destination:g' | sort | xargs mkdir
find 'Photo Dump' -type d -> List all folders in "Photo Dump"
sed -e 's:^Photo Dump:destination:g' - Since all folders listed in the above step will start with Photo Dump/..., we can just replace the beginning with the folder we want to copy the structure to (in this case I called it destination)
sort - Sorts results. This is required so that the parent folders are created before the children
xargs mkdir - Passes all the results from above into mkdir so it can create the folders

Related

Copy whole directory but exclude all folders and subfolders with certain name

I'm not allowed to use rsync on the cluster I'm working on so I need to use cp. I want to copy a large directory including all files and subfolders etc. but without any folders that have the name "outdir".
I tried cp -r -v ./!(outdir) ../target-directory/
but it still copies all folders and contents in deeper directories with the name outdir. It only included the outdir folders in the highest directory.
I also tried cp -r ./*/!(outdir) ../target-directory/ but that one copied all files into the folder without keeping any hirarchy or folders etc.
I also tried certain find commands but it didn't work, but maybe I was just doing something stupid. I'm a beginner with bash so if you could explain your answer and what the flags etc. do that would really be helpfull, I've been trying forever now, on what I think shouldn't be that hard to do.
Instead of cp, you can use tar with option --exclude to control what you want copied or not.
The full command is:
tar --exclude="outdir" -cvpf - . | (cd TARGET_DIRECTORY; tar -xpf -)
So any path that contains the "outdir" pattern will be excluded.
Without the --exclude option, it will copy the entire structure of your current directory under TARGET_DIRECTORY.
You can replace the . in the first tar by your desired source directory.

Bash Copying the Contents of One Directory to every Directory contained within a Parent Directory

I'd imagine this would be a simply command, but I can't find a way to copy the contents of a directory to every subdirectory contained in a parent directory. For example, let's say I wanted to copy the path:
user/origin
to all of the following directories inside the destination "target" directory. For example...
user/target/1, user/target/6, user/target/2, user/target/a/10, etc.
Is there any way to achieve this functionality?
Be careful because you can get an infinite loop, normally exec should suffice but when you are using recursion this way it causes an infinite loop so use xargs:
find user/target/ -type d | xargs -I {} cp -r user/origin {}

Copying multiple files with same name in the same folder terminal script

I have a lot of files named the same, with a directory structure (simplified) like this:
../foo1/bar1/dir/file_1.ps
../foo1/bar2/dir/file_1.ps
../foo2/bar1/dir/file_1.ps
.... and many more
As it is extremely inefficient to view all of those ps files by going to the
respective directory, I'd like to copy all of them into another directory, but include
the name of the first two directories (which are those relevant to my purpose) in the
file name.
I have previously tried like this, but I cannot get which file is from where, as they
are all named consecutively:
#!/bin/bash -xv
cp -v --backup=numbered {} */*/dir/file* ../plots/;
Where ../plots is the folder where I copy them. However, they are now of the form file.ps.~x~ (x is a number) so I get rid of the ".ps.~*~" and leave only the ps extension with:
rename 's/\.ps.~*~//g' *;
rename 's/\~/.ps/g' *;
Then, as the ps files have hundreds of points sometimes and take a long time to open, I just transform them into jpg.
for file in * ; do convert -density 150 -quality 70 "$file" "${file/.ps/}".jpg; done;
This is not really a working bash script as I have to change the directory manually.
I guess the best way to do it is to copy the files form the beginning with the names
of the first two directories incorporated in the copied filename.
How can I do this last thing?
If you just have two levels of directories, you can use
for file in */*/*.ps
do
ln "$file" "${file//\//_}"
done
This goes over each ps file, and hard links them to the current directory with the /s replaced by _. Use cp instead of ln if you intend to edit the files but don't want to update the originals.
For arbitrary directory levels, you can use the bash specific
shopt -s globstar
for file in **/*.ps
do
ln "$file" "${file//\//_}"
done
But are you sure you need to copy them all to one directory? You might be able to open them all with yourreader */*/*.ps, which depending on your reader may let browse through them one by one while still seeing the full path.
You should run a find command and print the names first like
find . -name "file_1.ps" -print
Then iterate over each of them and do a string replacement of / to '-' or any other character like
${filename/\//-}
The general syntax is ${string/substring/replacement}. Then you can copy it to the required directory. The complete script can be written as follows. Haven't tested it (not on linux at the moment), so you might need to tweak the code if you get any syntax error ;)
for filename in `find . -name "file_1.ps" -print`
do
newFileName=${filename/\//-}
cp $filename YourNewDirectory/$newFileName
done
You will need to place the script in the same root directory or change the find command to look for the particular directory if you are placing the above script in some other directory.
References
string manipulation in bash
find man page

Using 'cp' and preserving the attributes of a directory, but not copying any of it's children

I am making a file sync program. In order to increase the efficiency of the syncs, I have it sync/copy over only the new files/folders from the source. Anyway, when I copy directories into the sync I use 'cp pR itemName, because it preserves the attributes of the directory and the icon (if it is present). But, unfortunately it also copies all of the contained files in that directory... I do not want the children copied (excepting some invisible files), I want to copy one item at a time. Is there a way that I can programatically copy a directory, by itself (without including it's child files) but still retaining it's attributes (like Date Created and icon)?
You want to use rsync.
Rsync creates a list of all the files and copies only the ones that have been modified. This is really fast.
i do
rsync -avzr filesIwant WhereItShouldGo
but, to answer your question, you can list the fils and exclude one you dont want with grep and using xargs, run your action.
lets say you ran ls and this is what you got
#:~ cy$ ls
BackEnd Downloads Pictures
CSC 130 Library Public
Checkbook.java Movies Site and Code
Desktop Music Sites
Documents NetBeansProjects
and lets say that you wanted everything, just not anything in the music folder or the movies folder
you can do:
#:~ cy$ ls | grep -v Music | grep -v Movies
BackEnd
CSC 130
Checkbook.java
Desktop
Documents
Downloads
Library
NetBeansProjects
Pictures
Public
Site and Code
Sites
notice movies and Music were not listed. Well now you can run xargs and do the action. Since i dont want to delete anything, im not gonna do it, but this is what it would look like
#:~ cy$ ls | grep -v Music | grep -v Movies| xargs -I xx cp xx ToSomePlace
the -I command for xargs takes the input from the last command, and gives it a nickname, in my case "xx" so that you can call commands on xx knowing that they are each an element of the last command. Hope that helped.

Finding files with bash and copy to another location and reducing depth of folders

I'm trying to recover a mates hard drive, there is no structure what so ever so music and images are everywhere but in named folders sometimes >5 folders deep, I've managed to write a one-liner that finds the files and copies them to a mounted drive but it preserves the file structure completely. What I'm after is a bit of code that searches the drive and copies to another location and copies just the parent folder with the mp3/jpg files within and not the complete path. The other issue I have is the music is /folder/folder/folder/Artist/1.mp3..2.mp3..10.mp3 etc etc so I have to preserve the folder 'Artist' to give him any hope of finding his tracks again.
What I have working currently:
find /media/HP/ -name *.mp3 -fprintf /media/HP/MUSIC/Script.sh 'mkdir -p "/media/HP/MUSIC/%h" \n cp "%h/%f" "/media/HP/MUSIC/%h/"\n'
I then run the script.sh and it does all the copying.
Many Thanks
What you probably want to do will be along the lines of:
mkdir "$dest/$(basename $(dirname $source))"
OK folks - thanks for the input it did make me think deeper about this and I've come up with a result with the help of a colleague (thanks SiG):
This one-liner finds the files, and writes a script file to run separately but does copy across just the last folder as I wanted initially.
The Code:
find /some/folder/ -name *.mp3 | awk 'BEGIN{FS="/"}{print "mkdir -p \"/some/new/place/" $(NF-1) "\"\ncp -v -p \"" $0 "\" \"/some/new/place/" $(NF-1) "/" $NF "\""}' > script.sh
The output is:
mkdir -p "/media/HP/MUSIC/Satize" cp -v -p "/media/HP/Users/REBEKAH/Music/Satize/You Don't Love Me.mp3" "/media/HP/MUSIC/Satize/You Don't Love Me.mp3"
When script.sh is run it does all the work and I end up with a very reduced file structure I can copy to a new drive.
Thanks again folks much appreciated.
KjF
If you are doing the operation recursively ( entering directory by directory ), what you can do is everytime save your path as: Road_Dir=$(pwd)(let's say dir1/dir2/dir3/)
Then you detect your artist_name directory you save it is Music_Dir=$(pwd)
Finally you could extract your artist_name directory with the simple command:
Final_Dir=${Music_Dir##$Road_Dir/} (wich means take out the string $Road_Dir/ from $Music_Dir beginning from the left of $Music_Dir)
With this Final_Dir will contain artist_name, and you can copy your music file as $Final_Dir/Music.mp3 ...

Resources