Selectively create folders based on names in bash script - bash

I have several files called as follow:
dosulepin3D_CID_5284550.pdbqt
protriptyline3D_CID_4976.pdbqt
These are small molecules. Now I want to create a file in the Results folder for each one of these molecules, ignoring the 3D_CID_5284550.pdbqt they all have behind, and have folders called:
dosulepin
protriptyline
I want to do this with a for loop, since I'm also performing some functions with these files. This is what I have:
DIR="/home/roy/MolecularDocking/VirtualScreening/Dockings"
cd $DIR
for ligand in ligands/*; do
echo $ligand
mkdir "/home/roy/MolecularDocking/Results/$ligand"
done;
But this obviuosly creates folders with the full name.

Something like this.
DIR="/home/roy/MolecularDocking/VirtualScreening/Dockings"
cd "$DIR" || exit
for ligand in ligands/*.pdbqt; do
echo "$ligand"
echo mkdir -p "/home/roy/MolecularDocking/Results/${ligand%3D*}"
done
Remove the echo from the mkdir if you're satisfied with the output.
See Parameter Expansion for more details.

Related

going through directories in bash within for loops

I have a directory like this figure:
I have written a bash script that first goes to steady subdirectory, reads each folder inside it and performs tasks. Then it goes to transient subdirectory, loops over folders there and needs to map results through an openFOAM command that requires similar subfolder from other subdirectory (like mapping from steady/1 to transient/1). Both steady and transient folders are under same parent directory.
Basically, I want to find a way in the second for-loop to map from
"scale/steady/1" to "scale/transient/1" and the same for other subfolder (i.e. 2).
I know that I have to replace "1" in the second for loop with a varible .
Would some body assist me how I can do so?
for d in steady/*/
do
echo "$d"
(cd "$d" && touch steady.log&& simpleFoam > steady.log)
done
for i in transient/*/
do
echo "$i"
(cd $i && touch transient.log && mapFields ../../steady/1 -consistent)
done
for steady_folder in steady/*
do
transient_folder="${steady_folder/steady/transient}"
echo "$steady_folder"
.....
echo "$transient_folder"
.....
done

BASH Script for creating multiple directories, moving files, and then renaming said files

I am trying to make a bash script to create directories with the same name as each file in a given directory, then move said files to their respective directories, and then rename the files.
Basically - a quantum chemistry program that I use requires that the input files be named "ZMAT". So, if I have multiple jobs, I currently need to manually create directories, and then move the ZMAT files into them (can only run one job per folder).
When I run my code, I get "binary operator expected". I am not sure what this means. Some help please.
Here is what I have so far:
#!/bin/bash
if [ -e *.ZMAT ];
then
echo "CFOUR Job Detected"
for INPFILE in *.ZMAT; do
BASENAME=$(basename $INPFILE )
INPFILE=$BASENAME.ZMAT
OUTFILE=$BASENAME.out
XYZFILE=$BASENAME.xyz
ERRORFILE=$BASENAME.slu
if [ ! -e $ERRORFILE ];
then
# Create folder in scratch directory with the basename
mkdir /scratch/CFOUR/$BASENAME
# Move the file to its directory
mv -f $INPFILE /scratch/CFOUR/$BASENAME
# cd to the new directory
cd /scratch/CFOUR/$BASENAME
# Change the file name to just ZMAT
mv -f $INPFILE ZMAT
echo "Submitting CFOUR Job"
# Submit to scheduler
#RUN_COMMAND="sbatch -J $BASENAME _CFOUR_MRCC_SLURM.SUB"
#eval $RUN_COMMAND
else
echo "Error File Detected - Not Submitting Job"
fi
done
fi
An alternative would be to create symlinks to the original files.
As you said before, each ZMAT symlink would need to be in its own directory.
The upside is that the original data doesn't move, so less risk of breaking it, but the tool you want to use should read the symlinks as if they are the files it is looking for.
This one-liner creates an out directory in the current folder that you could subsequently move wherever you want it. You could easily create it where you do want it by replacing "out" with whatever absolute path you wanted
for i in *.ZMAT; do mkdir -p out/$i ; ln -s $PWD/$i out/$i/ZMAT ; done
I believe I have solved my problem. Here is the new script, which appears to be working fine. Any input is welcome though!
#!/bin/bash
SUBDIR=$(pwd)
for i in *.ZMAT; do
BASENAME=$(basename $i .ZMAT)
INPFILE=$BASENAME.ZMAT
OUTFILE=$BASENAME.out
XYZFILE=$BASENAME.xyz
ERRORFILE=$BASENAME.slu
if [ ! -e $ERRORFILE ];
then
mkdir /scratch/CFOUR/$BASENAME # Create Scratch Folder
cp $INPFILE /scratch/cdc/CFOUR/$BASENAME # Move Input to Scratch
cd /scratch/CFOUR/$BASENAME #cd to Scratch Folder
mv -f $INPFILE ZMAT # Change Input Name
echo "Submitting CFOUR Job"
# Submit to scheduler
#RUN_COMMAND="sbatch -J $BASENAME _CFOUR_MRCC_SLURM.SUB"
#eval $RUN_COMMAND
cd $SUBDIR #Go back to SUBDIR
else
echo "Error File Already Exists"
fi
done

Trying to write a MacOS automator script to make incrementing folders based off of scanned input

New to bash scripting, and I'm stuck. Within a static directory I'm trying to create a folder '001_scanned name' and within that directory create 6 more subfolders. I'm able to do it all brutishly with this code:
cd ~/deej/Test/Capture
mkdir "$1"
cd "$1"
mkdir "$1_1"
mkdir "$1_2"
mkdir "$1_3"
mkdir "$1_4"
mkdir "$1_5"
mkdir "$1_6"
Ugly, but works for now.
$1 is the scanned name and I was manually appending the prefix of the file names with "001, 002, etc.". Is there an easy way to do this within an Automator prompt since I'll be unable to keep the last variable stored in the code?
If you use the -p option with mkdir it will create intermediate directories as needed so you can do both commands at once. The seq function can create zero-padded integers:
for n in $(seq -f "%03g" 1 10);
do mkdir -p ${i}/${i}_${n};
done;
You can test using echo instead of mkdir -p. Below I had i set to 015...
015/015_001
015/015_002
015/015_003
015/015_004
015/015_005
015/015_006
015/015_007
015/015_008
015/015_009
015/015_010

Bash - Moving files from subdirectories

I am relatively new to bash scripting.
I need to create a script that will loop through a series of directories, go into subdirectories with a certain name, and then move their file contents into a common folder for all of the files.
My code so far is this:
#!/bin/bash
#used to gather usable pdb files
mkdir -p usable_pdbFiles
#loop through directories in "pdb" folder
for pdbDirectory in */
do
#go into usable_* directory
for innerDirectory in usable_*/
do
if [ -d "$innerDirectory" ] ; then
for file in *.ent
do
mv $file ../../usable_pdbFiles
done < $file
fi
done < $innerDirectory
done
exit 0
Currently I get
usable_Gather.sh: line 7: $innerDirectory: ambiguous redirect
when I try and run the script.
Any help would be appreciated!
The redirections < $innerDirectory and < $file are invalid and this is causing the problem. You don't need to use a loop for this, you can instead rely on the shell's filename expansion and use mv directly:
mkdir -p usable_pdbFiles
mv */usable_*/*.ent usable_pdbFiles
Bear in mind that this solution, and the loop based one that you are working on, will overwrite files with the same name in the destination directory.

Bash If then that reads a list in a file condition

Here is the condition:
I have a file with all packages installed.
I have a folder with all kinds of other packages, but they include all of the ones in the list, plus more.
I need a bash script that will read the file and check a folder for packages that don't exist in the list then remove them, they are not needed, but keep the packages that are on the list in that folder.
Or perhaps the bash should read folder then if packages in the folder aren't on the list them rm -f that or those packages.
I am familiar with writing if then conditional statements, I just don't know how to do if making the items in the list a variable or variables (in a loop).
thanks!
I would move the packages on the list to a new folder, delete the original folder, and move the temporary folder back:
DIR=directory-name
mkdir "$DIR-tmp"
while read pkgname; do
if [[ -f "$DIR/$pkgname" ]]; then
mv "$DIR/$pkgname" "$DIR-tmp"
fi
done < package-list.txt
# Confirm $DIR-tmp has the files you want first!
rm -rf "$DIR"
mv "$DIR-tmp" "$DIR"
I think you want something like this:
for file in $(ls folder) ; do
grep -E "$file" install-list-file >/dev/null || \
echo $file
done > rm-list
vi rm-list # view file to ensure correct
rm $(<rm_list)
There are ways to make this faster (using parameter substitution to avoid fork/exec's), but I recommend avoiding fancy shell stuff [${file##*/}] until you've got the basics down. Also, this script basically translates the description into a script and is not intended to be much more than a guide on how to approach the problem.

Resources