Recursively strip pattern from filename? - shell

Is there a way for me to use the find command to recursively loop through a directory and strip a pattern from the filename?
For example, if I have:
styles.css?c=123456
as a saved file, I would like to be able to loop through the files and match anything that has the wildcard *.css?* and then turn that styles.css?c=123456 into styles.css.

Try this:
find -type f -name '*.css*' -exec echo 'FILE="{}"; mv ${FILE} ${FILE%\?*} ' \; | bash

Related

Renaming multiple files in a nested structure

I have a directory with this structure:
root
|-dir1
| |-pred_20181231.csv
|
|-dir2
| |-pred_20181234.csv
...
|-dir84
|-pred_2018123256.csv
I want to run a command that will rename all the pred_XXX.csv files to pred.csv.
How can I easily achieve that?
I have looked into the rename facility but I do not understand the perl expression syntax.
EDIT: I tried with this code: rename -n 's/\training_*.csv$/\training_history.csv/' *.csv but it did not work
Try with this command:
find root -type f -name "*.csv" -exec perl-rename 's/_\d+(\.csv)/$1/g' '{}' \;
Options used:
-type f to specify file or directory.
-name "*.csv" to only match files with extension csv
-exec\-execdir to execute a command, in this case, perl-rename
's/_\d+(\.csv)/$1/g' search a string like _20181234.csv and replace it with .csv, $1 means first group found.
NOTE
Depending in your S.O. you could use just rename instead of perl-rename.
Use some shell looping:
for file in **/*.csv
do
echo mv "$(dirname "$file")/$(basename "$file")" "$(dirname "$file")/pred.csv"
done
On modern shells ** is a wildcard that matches multiple directories in a hierarchy, an alternative to find, which is a fine solution too. I'm not sure if this should instead be /**/*.csv or /root/**/*.csv based on tree you provided, so I've put echo before the 'mv' to see what it's about to do. After making sure this is going to do what you expect it to do, remove the echo.

Get all occurrences of a string within a directory(including subdirectories) in .gz file using bash?

I want to find all the occurrences of "getId" inside a directory which has subdirectories as follows:
*/*/*/*/*/*/myfile.gz
i tried thisfind -name *myfile.gz -print0 | xargs -0 zgrep -i "getId" but it didn't work. Can anyone tell me the best and simplest approach to get this?
find ./ -name '*gz' -exec zgrep -aiH 'getSorById' {} \;
find allows you to execute a command on the file using "-exe" and it replaces "{}" with the file name, you terminate the command with "\;"
I added "-H" to zgrep so it also prints out the file path when it has a match, as its helpful. "-a" treats binary files as text (since you might get tar-ed gzipped files)
Lastly, its best to quote your strings in case bash starts globbing them.
https://linux.die.net/man/1/grep
https://linux.die.net/man/1/find
Use the following find approach:
find . -name *myfile.gz -exec zgrep -ai 'getSORByID' {} \;
This will print all possible lines containing getSORByID substring

Bash Script for listing subdirectories and files in textfile

I need a Script that writes the directory and subdirectory in a text-file.
For example the script lies in /Mainfolder and in this folder are four other folders. Each contains several files.
Now I would like the script to write the path of each file in the textfile.
Subfolder1/File1.dat
Subfolder1/File2.dat
Subfolder2/File1.dat
Subfolder3/File1.dat
Subfolder4/File1.dat
Subfolder4/File2.dat
Important is that there is no slash in front of the listing.
Use the find command:
find Mainfolder > outputfile
and if you only want the files listed, do
find Mainfolder -type f > outputfile
You can also strip the leading ./ if you search the current directory, with the %P format option:
find . -type f -printf '%P\n' > outputfile
If your bash version is high enough, you can do it like that:
#!/bin/bash
shopt -s globstar
echo ** > yourtextfile
This solution assumes that the subdirectories contain only files -- they do not contain any directory in turn.
find . -type f -print | sed 's|^.*/S|S|'
I have created a single file in each of the four subdirectories. The original output is:
./Subfolder1/File1.dat
./Subfolder4/File4.dat
./Subfolder2/File2.dat
./Subfolder3/File3.dat
The filtered output is:
Subfolder1/File1.dat
Subfolder4/File4.dat
Subfolder2/File2.dat
Subfolder3/File3.dat
You can use this find with -exec:
find . -type f -exec bash -c 'f="{}"; echo "${f:2}"' \;
This will print all files starting from current paths by removing ./ from front.

parsing and changing the files in all sub directories

I would like to parse all the files *.c in the sub directories and prefix a string to the file name and place file in the same sub-directory.
For example, if there's a file in dir1/subdir1/test.c , I would like to change that file name to xyztest.c and place it in dir1/subdir1/. How to do that?
I would like to do in bash script.
Thanks,
What you need is:
Find all c files in a directory (use find command)
Separate the filname and dirname (use basename and dirname)
Move dirname/filename to dirname/prefix_filename
That should do it.
A find command with while loop should do that:
PREFIX=xyz;
while read line
do
path="$(dirname $line)"
base="$(basename $line)";
mv "${line}" "$path/${PREFIX}${base}"
done < <(find dir1 -name "*.c")
find dir -name '*.c' -printf 'mv "%p" "%h/xyz%f"\n' | sh
This will fail if you have file names with double quotes, or varous other shell metacharacters; but if you don't, it's a nice one-liner.

Shell script traversing the all subdirectories and modifying the content of files

I need to modify a number of files inside a directory. I need to modify all those files which contain particular text and have to replace with some new text.
So I thought of writing a shell script which will traverse through all the subdirectories and modify the content but I'm having problem while traversing the all possible directories.
You can use find to traverse through subdirectories looking for files and then pass them on to sed to search and replace for text.
e.g.
find /some/directory -type f -name "*.txt" -print -exec sed -i 's/foo/bar/g' {} \;
will find all txt files and replace foo with bar in them.
The -i makes sed change the files in-place. You can also supply a backup-suffix to sed if you want the files backed up before being changed.
GNU find
find /some_path -type f -name "*.txt" -exec sed -i 's/foo/bar/g' "{}" +;
http://git.savannah.gnu.org/cgit/bash.git/tree/examples/functions/recurse
:)
You want find.
for n in $(find | grep txt$)
do
echo $n
modify_content.sh $n
done

Resources