Bash Rename Files Script Not Working - linux

I have the following script and for some reason it is not working
find . -name '*---*' | while read fname3
do
new_fname3=`echo $fname3 | tr "---" "-"`
if [ -e $new_fname3 ]
then
echo "File $new_fname3 already exists. Not replacing $fname3"
else
echo "Creating new file $new_fname3 to replace $fname3"
mv "$fname3" $new_fname3
fi
done
However if I use
find . -name '*---*' | while read fname3
do
new_fname3=`echo $fname3 | tr "-" "_"`
if [ -e $new_fname3 ]
then
echo "File $new_fname3 already exists. Not replacing $fname3"
else
echo "Creating new file $new_fname3 to replace $fname3"
mv "$fname3" $new_fname3
fi
done
The script works but I end up with 3 underscores "_" how can I replace the 3 dashes "---" with a single dash?
Thanks,

Have a look at man tr. tr will just replace single characters.
Use something like perl -wpe "s/---/-/" instead.
Also have a look at man 1p rename. It is doing pretty much exactly what you want:
rename 's/---/-/' *---*

I believe you need to change the tr for a sed substitution:
tr '---' '-' should be changed to sed -e 's/---/-/g
As an example of the difference:
$ echo "a---b" | tr '---' '-'
tr: unrecognised option '---'
try `tr --help' for more information
$ echo "a---b" | sed -e 's/---/-/g'
a-b

Related

linux shell script sed

#!/bin/sh -x
if [[ $# -eq 0 ]];then
echo "usage: makeSoln <customer name>"
exit
fi
echo "Customer Name is set to : $1"
if [ -d "$1" ]; then
echo "Solution for $1 already exists!! Please delete it before running this."
exit 1;
fi
if [ -e "$1" ]; then
echo "A file by name '$1' exists!! Please delete it before running this."
exit 1;
fi
cp -R SolnTemplate $1
cd $1
find . -name "pom.xml" | xargs sed -i xx 's/SolnTemplate/'$1'/g'
When i given this and execute this file i am gettting this error:
+ xargs sed -e xx s/SolnTemplate/Reliance/g
sed: -e expression #1, char 2: extra characters after command
To begin, replace:
find . -name "pom.xml" | xargs sed -i xx 's/SolnTemplate/'$1'/g'
With:
find . -name "pom.xml" | xargs sed -ixx 's/SolnTemplate/'$1'/g'
The above removes the space between -i and xx. Because you are on Linux, you are using GNU sed and, unlike BSD sed, it does not accept a space between -i and the backup suffix.
Also, just in case $1 includes a space in the name, it should be enclosed in double-quotes:
find . -name "pom.xml" | xargs sed -ixx 's/SolnTemplate/'"$1"'/g'
This still requires care that you don't unintentionally include any sed-active characters in $1.
i didnt go over all of the script, but this command:
sed -i xx 's/SolnTemplate/'$1'/g'
should be:
sed -ixx 's/SolnTemplate/"$1"/g'
because the ' is from outside, you need to put in the inside "

Creating a directory name based on a file name

In my script I am taking a text file and splitting into sections. Before doing any splitting, I am reformatting the name of the text file. PROBLEM: Creating a folder/directory and naming it the formatted file name. This is where segments are placed. However the script breaks when the text file has spaces in it. But that is the reason I am trying to reformat the name first and then do the rest of the operations. How could I do so in that sequence?
execute script: text_split.sh -s "my File .txt" -c 2
text_split.sh
# remove whitespace and format file name
FILE_PATH="/archive/"
find $FILE_PATH -type f -exec bash -c 'mv "$1" "$(echo "$1" \
| sed -re '\''s/^([^-]*)-\s*([^\.]*)/\L\1\E-\2/'\'' -e '\''s/ /_/g'\'' -e '\''s/_-/-/g'\'')"' - {} \;
sleep 1
# arg1: path to input file / source
# create directory
function fallback_out_file_format() {
__FILE_NAME=`rev <<< "$1" | cut -d"." -f2- | rev`
__FILE_EXT=`rev <<< "$1" | cut -d"." -f1 | rev`
mkdir -p $FILE_PATH${__FILE_NAME};
__OUT_FILE_FORMAT="$FILE_PATH${__FILE_NAME}"/"${__FILE_NAME}-part-%03d.${__FILE_EXT}"
echo $__OUT_FILE_FORMAT
exit 1
}
# Set variables and default values
OUT_FILE_FORMAT=''
# Grab input arguments
while getopts “s:c” OPTION
do
case $OPTION in
s) SOURCE=$(echo "$OPTARG" | sed 's/ /\\ /g' ) ;;
c) CHUNK_LEN="$OPTARG" ;;
?) usage
exit 1
;;
esac
done
if [ -z "$OUT_FILE_FORMAT" ] ; then
OUT_FILE_FORMAT=$(fallback_out_file_format $SOURCE)
fi
Your script takes a filename argument, specified with -s, then modifies a hard-coded directory by renaming the files it contains, then uses the initial filename to generate an output directory and filename. It definitely sounds like the workflow should be adjusted. For instance, instead of trying to correct all the bad filenames in /archive/, just fix the name of the file specified with -s.
To get filename and extension, use bash's string manipulation ability, as shown in this question:
filename="${fullfile##*/}"
extension="${filename##*.}"
name="${filename%.*}"
You can trim whitespace from the input string using tr -d ' '.
You can then join this to your FILE_PATH variable with something like this:
FILE_NAME=$(echo $1 | tr -d ' ')
FILE_PATH="/archive/"
FILE_PATH=$FILE_PATH$FILE_NAME
You can escape the space using a back slash \
Now the user may not always provide with the back slash, so the script can use sed to convert all (space) to \
sed 's/ /\ /g'
you can obtain the new directory name as
dir_name=`echo $1 | sed 's/ /\ /g'

Can't rename a file name

I have a small bash script that download and rename files. The problem is with some gibberish not standard characters that bash can't understand.
for example:
�������� ���� ���'�-2.jpg
my bash
while read line; do
if [ ! -z "$line" ]; then
NEW_FILENAME=$(echo "$line" | uniconv -encode Russian-Translit | uniconv -encode Latin | tr -d '\[\]\!\#\#\$\%\^\&\*\(\)\?\'')
mv "$line" "$NEW_FILENAME"
fi
done <<< "$FILES_TO_CONVERT"
why don't you delete those characters with something like :
sed 's/[^a-zA-Z0-9_\.-]//g'

sed or operator in set of regex

The bash script I wrote is supposed to modify my text files. The problem is the speed of operation. There are 4 lines of each file I want to modify.
This is my bash script to modify all .txt files in a given folder:
srcdir="$1" //source directory
cpr=$2 //given string argument
find $srcdir -name "*.txt" | while read i; do
echo "#############################"
echo "$i"
echo "Custom string: $cpr"
echo "#############################"
# remove document name and title
sed -i 's_document=.*\/[0-9]\{10\}\(, User=team\)\?__g' $i
# remove document date
sed -i 's|document date , [0-9]\{2\}\/[0-9]\{2\}\/[0-9]\{4\} [0-9]\{2\}:[0-9]\{2\}:[0-9]\{2\} MDT||g' $i
# remove document id
sed -i 's|document id = 878h67||g' $i
# replace new producer
sed_arg="-i 's|Reproduced by $cpr|john smith|g' $i"
eval sed "$sed_arg"
done
I dont know how to concatinate all my sed commands in one command or two, so the job would be done faster ( I think! )
I have tried the OR operator for regex | but no success.
Have you tried
sed -i -e 's/pattern/replacement/g' -e 's/pattern1/replace1/g' file
sed -i '
s_document=.*\/[0-9]\{10\}\(, User=team\)\?__g;
s|document date , [0-9]\{2\}\/[0-9]\{2\}\/[0-9]\{4\} [0-9]\{2\}:[0-9]\{2\}:[0-9]\{2\} MDT||g;
s|document id = 878h67||g;
s|Reproduced by '"$cpr"'|john smith|g' $i

How can I add a string to the beginning of each file in a folder in bash?

I want to be able to prepend a string to the beginning of each text file in a folder. How can I do this using bash on Linux?
This will do that. You could make it more efficient if you are doing the same text to each file...
for f in *; do
echo "whatever" > tmpfile
cat $f >> tmpfile
mv tmpfile $f
done
You can do it like this without a loop and cat
sed -i '1i whatever' *
if you want to back up your files, use -i.bak
Or using awk
awk 'FNR==1{$0="whatever\n"$0;}{print $0>FILENAME}' *
And you can do this using sed in 1 single command as well
for f in *; do
sed -i.bak '1i\
foo-bar
' ${f}
done
This should do the trick.
FOLDER='path/to/your/folder'
TEXT='Text to prepend'
cd $FOLDER
for i in `ls -1 $FOLDER`; do
CONTENTS=`cat $i`
echo $TEXT > $i # use echo -n if you want the append to be on the same line
echo $CONTENTS >> $i
done
I wouldn't recommending doing this if your files are very big though.
You can do this as well:
for f in *; do
cat <(echo "someline") $f > tempfile
mv tempfile $f
done
It's not much different from the 1st post but does show how to treat the output of the 'echo' statement as a file without having to create a temporay file to store the value.
You may use the ed command to do without temporary files if you like:
for file in *; do
(test ! -f "${file}" || test ! -w "${file}") && continue # sort out non-files and non-writable files
if test -s "${file}" && ! grep -Iqs '.*' "${file}"; then continue; fi # sort out binary files
printf '\n%s\n\n' "FILE: ${file}"
# cf. http://wiki.bash-hackers.org/howto/edit-ed
printf '%s\n' H 0a "foobar" . ',p' q | ed -s "${file}" # dry run (just prints to stdout)
#printf '%s\n' H 0a "foobar" . wq | ed -s "${file}" # in-place file edit without any backup
done | less
This is the easiest I have worked out.
sed -i '1s/^/Text to add then new file\n/' /file/to/change
Here is an example :
for f in *;
do
mv "$f" "whatever_$f"
done
A one-liner: rename '' string_ *

Resources