"for loop" to run rsync on relevant folders only - bash

I have a folder contains around 650 folders (source), I generated a list of the relevant folders i want (final.txt).
i am trying to use a "for loop" to copy only the relevant sub-folders to a new location (target).
i keep getting the original content of the "source" copied to the "target".
i run:
for var in `cat final.txt` ; do rsync -ah $var source/ target/ ; done
I tried different syntax but can't seem to get what I need.
what am i doing wrong?
I expect to copy only the folders which name is in the final.txt list copied to the target (all "names" in the file are a single word, matching to some of the folder names for exactly)

ok after messing around I should have ran this (it works)
for var in `cat final.txt` ; do rsync -ah source/$var target/ ; done

Related

Moving files into new subdirectory, except for existing folders?

A Redditor had written me a great script that allowed me to move all the files in a series of folders into a new subdirectory in all those folders called New. However, I also have pre-existing folders (namely just 1 called "Journals") that have had their files moved into a subdirectory called New, as well.
How would I modify the following script (on Windows) to not touch any folders within the folders, or perhaps not touch any folder called Journals?
For example, the current directory looks like:
Parent/Folder name/tons of files/
Parent/Folder name/Journals/tons of files
(folder name = random string of alphanumeric numbers in the thousands). Each folder has a ton of files, and a folder called Journals.
I would like:
Parent/randomstring folder/New/tons of files/
Parent/randomstring folder/Journals/tons of files
The code they wrote for me:
# Run from search root
cd "O:\..."
# Change this to taste
export NEWDIR=New
find . | egrep '(mp4$|jpg$|png$)' |
while read FILE
do
BASEDIR=$(dirname "$FILE")
mkdir "$BASEDIR/$NEWDIR" > /dev/null 2>&1
mv "$FILE" "$BASEDIR/$NEWDIR"
done
This code would do the following:
Parent/randomstring folder/New/tons of files/
Parent/randomstring folder/Journals/new/tons of files

Mac OS - Batch Rename All Files in Folder but Disregard All SubFolders

I have a bunch of folders that I would like to rename all the files contained within minus any subdfolders.
For example lets say I have two parent folders:
ParentFolder1 - [PF1]
ParentFolder2 - [PF2]
Each parent folder has various amounts of subfolders:
SubParentFolder1_1
SubParentFolder1_2
SubParentFolder2_1
Inside the ParentFolder and each SubParentFolder there can be files such as .mp3, .txt. etc. or more subfolders.
How would I go about renaming all and any files in this manner:
example.mp3 -> example - [PF1]
example.txt -> example - [PF2]
example.docx -> example - [PF2]
Appreciate any input!
This is a way to list files (not folders) in a range of directories and then do something with them... Specifics of renaming are up to you.
for FOLD in Parent*;
do for FILE in $(ls -p $FOLD | grep -v "/");
do echo "$FOLD/$FILE" "$FOLD/${FILE%.*}";
done; done;
Explanation:
For each folder (FOLD) in directories matching the wildcard Parent*,
list the contents, adding / to the end of directory names.
Do inverse grep on that list, leaving just the file names.
Loop through each FILE and echo out the original folder+file, followed by the folder and file with the suffix removed by patten matching.
Once you test this, you can replace echo with mv to do the actual renaming... (I've put these on separate lines to make them more readable, but would usually run this as one long command.

How to recursively rename all files and folder including specific part of the filename with Windows Bash?

This has to be a duplicate but I have read and tried at least a dozen of Q&As here on SO, and I cannot get any of them working for my case.
Really hope this won't result in downvotes because of it.
So I'm on Windows (10) and have a Bash terminal that I want to use for my task. The MINGW64 one I downloaded when I started working with Git.
I would prefer the solution with this program, but will be perfectly happy with one in Command Prompt Terminal or even PowerShell.
I created a TemplateApp which is in C:\Apps\TemplateApp folder which has multiple folders and subfolders named TemplateApp or TemplateApp.something as well as a lot of files that have TemplateApp as a part of their name.
Could be:
TemplateApp.ext
TemplateApp.something.ext
something.TemplateApp.something.ext
Then I copied the uppermost folder to C:\Apps\TemplateApp - Copy and in turn renamed it to C:\Apps\ProductionApplication.
Now for the love of whomever, I cannot make any of the scripts I found on SO to work for my case, ie. to rename all the above mentioned files and folders by replacing TemplateApp with ProductionApplication.
Here is a bash function I wrote that I think does very much like what you are wanting to do.
function func_CreateSourceAndDestination() {
#
for (( i = 0 ; i < ${#files_syncSource[#]} ; i++ )) ; do
files_syncDestination[${i}]="${files_syncSource[${i}]#${directory_MusicLibraryRoot_source}}"
file_destinationPath="$( dirname -- "${directory_PMPRoot_destination}${files_syncDestination[${i}]}" )"
if [ ! -d "${file_destinationPath}" ] ; then
mkdir -p "${file_destinationPath}"
fi
rsync -rltDvPmz "${files_syncSource[${i}]}" "${directory_PMPRoot_destination}${files_syncDestination[${i}]}"
done
}
In my case I'm feeding into rsync for a source and a destination. I'm pulling all the file paths from an array that has been split into path segments. I have to make certain character substitutions for FAT and NTFS file systems. I do this recursively.
files_syncDestination[${i}]="${files_syncDestination[${i}]//\:/__}"
That's the magic. I load a new array with the character substituted. You could do the same with a loaded variable including your phrases for change.
files_syncDestination[${i}]="${files_syncDestination[${i}]//${targetPhrase}/${subPhrase}}"
After that change in the function, you could use rsync or cp or mv as you prefer to go from your source array to your destination array.
(The double-slash in the substitution makes the substitution global.)

How to create multiple files in each directories and then compress it through tar (BASH)

What I am currently struggling is to create multiple files and storing it into each directory.
I have made 100 directories like this:
mkdir ./dir.{01..100}
What I want is to create 100 text files for each directory. So that the result will show like:
click on dir.01 at home dir, which has files named: 01.txt to 100.txt
Also, I want to compress all 100 directories, each containing 100 text files into one using tar.
I am struggling with:
creating 100 text files each in 100 directories
using tar to zip all 100 directories together.
I am more interested in making creating 100 text files IN 100 directories. Also I am MUCH MORE interested in how to use tar to join all 100 directories together in specific file (fdtar) for instance.
If you are fine with empty files,
touch ./dir.{01..100}/{01..100}.txt
If you need each file to contain something, use that as the driver in a loop:
for file in ./dir.{01..100}/{01..100}.txt; do
printf "This is the file %s\n" "$file">"$file"
done
This could bump into ARG_MAX ("argument list too long") on some platforms, but it works fine on MacOS and should work fine on any reasonably standard Linux.
Splitting the loop into an inner and an outer loop could work around that problem:
for dir in ./dir.{01..100}; do
for file in {01..100}.txt; do
printf "This is file %s/%s\n" >"$dir/$file"
done
done
If I understand you need two things. First, you have 100 directories and need to create a file in each. With a for loop in bash run from the parent directory where all other directories you have created are:
for n in dir.*
do
f=`echo $n | sed s/dir\.//`
echo "This is file $n" >"$n/$f.txt"
done
Regarding tar that is even easier because tar will take multiple directories and glue them together. From the parent directory try:
tar cvf fd.tar dir.*
The c option will create the archive. v will tell tar to print all it is doing so you know what is happening. f directories.tar will create the archive with that name.
When you undo the tar operation, you will use:
tar xvf fd.tar
In this case x will extract the contents of the tar archive and will create all 100 directories for you at the directory from which you invoke it.
Note that I have used fd.tar and not fdtar as the .tar extension is the customary way to signal that the file is a tar archive.

looping files with bash

I'm not very good in shell scripting and would like to ask you some question about looping of files big dataset: in my example I have alot of files with the common .pdb extension in the work dir. I need to loop all of them and i) to print name (w.o pdb extension) of each looped file and make some operation after this. E.g I need to make new dir for EACH file outside of the workdir with the name of each file and copy this file to that dir. Below you can see example of my code which are not worked- it's didn't show me the name of the file and didn't create folder for each of them. Please correct it and show me where I was wrong
#!/bin/bash
# set the work dir
receptors=./Receptors
for pdb in $receptors
do
filename=$(basename "$pdb")
echo "Processing of $filename file"
cd ..
mkdir ./docking_$filename
done
Many thanks for help,
Gleb
If all your files are contained within the .Repectors folder, you can loop each of them like so:
#!/bin/bash
for pdb in ./Receptors/*.pdb ; do
filename=$(basename "$pdb")
filenamenoextention=${filename/.pdb/}
mkdir "../docking_${filenamenoextention}"
done
Btw:
filenamenoextention=${filename/.pdb/}
Does a search replace in the variable $pdb. The syntax is ${myvariable/FOO/BAR}, and replaces all "FOO" substrings in $myvariable with "BAR". In your case it replaces ".pdb" with nothing, effectively removing it.
Alternatively, and safer (in case $filename contains multiple ".pdb"-substrings) is to remove the last four characters, like so: filenamenoextention=${filename:0:-4}
The syntax here is ${myvariable:s:e} where s and e correspond to numbers for the start and end index (not inclusive). It also let's you use negative numbers, which are offsets from the end. In other words: ${filename:0:-4} says: extract the substring from $filename starting from index 0, until you reach fourth-to-the-last character.
A few problems you have had with your script:
for pdb in ./Receptors loops only "./Receptors", and not each of the files within the folder.
When you change to parent directory (cd ..), you do so for the current shell session. This means that you keep going to the parent directory each time. Instead, you can specify the parent directory in the mkdir call. E.g mkdir ../thedir
You're looping over a one-item list, I think what you wanted to get is the list of the content of ./Receptors:
...
for pdb in $receptors/*
...
to list only file with .pdb extension use $receptors/*.pdb
So instead of just giving the path in for loop, give this:
for pdb in $receptors/*.pdb
To remove the extension :
set the variable ext to the extension you want to remove and using shell expansion operator "%" remove the extension from your filename eg:
ext=.pdb
filename=${filename%${ext}}
You can create the new directory without changing your current directory:
So to create a directory outside your current directory use the following command
mkdir ../docking_$filename
And to copy the file in the new directory use cp command
After correction
Your script should look like:
receptors=./Receptors
ext=.pdb
for pdb in $receptors/*.pdb
do
filename=$(basename "$pdb")
filename=${filename%${ext}}
echo "Processing of $filename file"
mkdir ../docking_$filename
cp $pdb ../docking_$filename
done

Resources