Bash loop through directory and rename every file - bash

I am horrible at writing bash scripts, but I'm wondering if it's possible to recursively loop through a directory and rename all the files in there by "1.png", "2.png", etc, but I need it to restart at one for every new folder it enters. Here's script that works but only does it for one directory.
cd ./directory
cnt=1
for fname in *
do
mv $fname ${cnt}.png
cnt=$(( $cnt + 1 ))
done
Thanks in advance
EDIT
Can anyone actually write this code out? I have no idea how to write bash, and it's very confusing to me

Using find is a great idea. You can use find with the next syntax to find all directories inside your directory and apply your script to found directories:
find /directory -type d -exec youscript.sh {} \;
-type d parameter means you want to find only directories
-exec youscript.sh {} \; starts your script for every found directory and pass it this directory name as a parameter

Use find(1) to get a list of files, and then do whatever you like with that list.

Related

Renaming all files within subdirectories

I am trying to rename all the files with certain regex patterns within the same subdirectory. Right now, I am in the current directory (above all the sub directories) and am running the following code:
for d in */ ; do
cp $d*hw4*.pl $dhw4.pl
done
I wish to find all the files with hw4 in them, and rename them to hw4.pl and keep them in the same directory. Could someone assist me with this? I know you can do this with the mv command, but I don't want to make a mistake, so I am using copy for now.
Thank you.
I suggest to use find, like this:
find . -type f -name '*hw4*' -execdir mv {} hw4.pl \;

How to handle additional directories in bash shell

I have a zip file named agent-20.1.80.8366.zip, when I extract this zip it is giving additional directory inside the parent dir like below:
agent-20.1.80.8366/agent-20.1.80.8366/files
I would like to extract and move files from child directory to it's parent directory and remove that empty child directory and then I want to pass that path as a variable.
Please someone help with bash snippet that should strictly validate and proceed, and then parent path should be stored in a variable
expected output to be:
agent-20.1.80.8366/files
$ mv agent-20.1.80.8366/agent-20.1.80.8366/files agent-20.1.80.8366/files
$ rmdir agent-20.1.80.8366/agent-20.1.80.8366
This will fail if agent-20.1.80.8366/agent-20.1.80.8366 is not empty, which imo is a good thing, since you are assuming that it will empty if files is moved.
Using find to first move the file up one level
find agent-20.1.80.8366/agent-20.1.80.8366 -type f -execdir mv -f '{}' .. \;
Then using find to remove the remaining directory
find agent-20.1.80.8366 -type d -name "agent-20.1.80.8366" -delete

Find all dir's called "example", set it and its contents writable

I have a site, with some template directories, there are a few modules, each with their own template dir (So there are N dirs called templates).
Each of those dirs has a dir in it, called translated. I need a script to set all those dirs and it's contents writable.
I prefer this via a loop so I can echo the result. My shell skills are (still) very minimal, I can't seem to combine them, I can find the dirs from the current working directory, but I can't seem to get it recursive:
for f in ./*/translated/
do
echo $f
done
This only finds ./templates/translated/, but not ./some/dirs/deeper/translated/
I can use $f now for a chmod a+rw, but this will only set the contents writable, how do I also get the dir itself? I need new files to be written in it too.
Summery:
1) How do I make it recursive?
2) How do I set the dir itself to +rw?
The tool for finding stuff recursively is called find.
find . -name 'translated' -type d -exec echo chmod -R u+rw {} +
Take out the echo if you are satisfied with the results. If your find does not support -exec ... + then try with -exec ... \; instead.
Some shells have a wildcard ** which will do the same thing, but then your script will be tied to that particular shell.

How to rename multiple directories in bash using a symbol pattern

I am very new to bash so please don't overcomplicate the answer!
I have roughly 200 sub-directories each named similarly to this. (I think they are sub directories. They live within another directory at least.)
XMMXCS J083454.8+553420.58
I need to bulk rename all of these directories and change the '+' in the directory name to '-'.
To change the names of my directory I have tried:
find . -depth -type d -name + -exec sh -c 'mv "${0}" "${0%/+}/-"' {} \;
and
find . -name + -type d -execdir mv {} - \
However I think this isn't working because + and - aren't letter characters.
How do I get around this?
Everything I have found online relates to renaming files as opposed to directories, and if anyone knows how to get round this without having to rename them all manually it would be very appreciated.
This previous question I have tried and the syntax doesn't work for me. The folders are all called the same thing after running.
Rename multiple directories matching pattern
Thanks
You can have a script like this.
#!/bin/bash
DIR='.' ## Change to the directory you want.
for SDIR in "$DIR"/*; do
[[ -d $SDIR ]] || continue ## Skip if it's not a directory
BASE=${SDIR##*/} ## Gets the base filename (removes directory part)
NEW_NAME=${BASE//+/-} ## Creates a new name based from $BASE with + chars changed to -
echo mv -- "$SDIR" "$DIR/$NEW_NAME" ## Rename. Remove echo if you think it works the right way already.
done
Then run bash script.sh.
Your original syntax was pretty close, try something like this
find -mindepth 1 -maxdepth 1 -type d -name '*+*' -exec bash -c 'mv "${0}" "${0//+/-}"' {} \;
Issues
-depth Performs a dfs traversal, but it seems like you only want directories one level deep
You need to match globs that contain +. So *+* and not just + (quoting is needed with globs so they get processed by find and not the shell)
With "${0%/+}/-" you seem to be mixing up a few syntaxes, ${0//SUBSTRING/TO_REPLACE} with replace all instances of SUBSTRING with TO_REPLACE

"for" loop in shell that go over directories

I have a directory of 24 sub-directories, no chronological order
I need to enter a sub directory, unzip a file there and then call "tophat" command on the unzipped file, then move to the next sub-directory. the loop should go over all the sub-directories with these commands.
I don't really know how to create this loop (I need it to run on a display and not according to numeric order)
(for sure many of you who work with RNA-seq results are familiar with this issue)
If anyone can help me with it
I'll be very thankful
for d in "/path/to/"*/
do
cd "$d" || continue
unzip the_file.zip
tophat the_file
done
Use find:
find /path -type d -print | \
while read path ; do
...
done
Note: This loop breaks when the file names contain new line characters.
Same using for loop
for directory in `find /path -type d -print`
do
cd "$directory"
unzip zip_filename
sh zip_dir/script_file.sh &
done

Resources