Bash: Moving multiple files into subfolders - bash

I have a folder with a couple thousand files and I want to move them into subfolders according to a string in the filename. The files all have a structure like
something-run1_001.txt
something-run22_1243.txt
So I tried the following script in order to move all files with "run1" in it into a subfolder r1 and all "run22" files in a subfolder r22 (and so on) but it does no work that way and I get a message "File X is the same as file X".
#!bin/bash
for i in {1..39}
do
foldername=r$i
#echo "$foldername"
mkdir $foldername
find . -type f -name "*run$i_*" | xargs -i mv {} $foldername/
done
How to solve this?

for i in {1..39}
do
mkdir -p r${i}/
mv *run${i}_* r${i}/
done

is this work as your requirement?
mv *run*.html dir1

If you still run into the "too many arguments" trap you can pipe find into a while loop
#!/bin/bash -u
find . -maxdepth 1 -name '*-run*_*.txt' |
{
while read FNAME
do
N=${FNAME##*-run}
N=${N%_*}
DIR=r$N
test -d $DIR || mkdir $DIR
mv $FNAME $DIR/.
done
}

Related

script to remove middle character from multiple directories then rename files in subdirectories to include directory + file name

I have two objectives I am trying to accomplish and need some help.
Here is the overview:
There are hundreds of folders/directories with random numbers ( 5555#5555 ) containing the same 001.pdf file. I would like to:
1: Remove the "#" symbol from every folder/directory
2: Rename the 001.pdf file to include the new folder numbers and the 001.pdf
Desired result: The folder 5555#5555 become 55555555 containing the 001.pdf file that becomes 55555555.001.pdf
Hope that makes sense and thanks.
for f in *#*;
do
newFolder=$(echo ${f//%})
mv $f $newFolder
newFile=$(printf $newFolder".001.pdf")
mv $newFolder/001.pdf $newFolder/$newFile
done
This should do it, although there may be more elegant solutions. Change the regular expressions for the loop if you want to catch other files without #.
so update: Thanks for the suggestions. Here is what I got to work for me. Might not be the best way but hey.
curdir=`pwd`
for f in `find . -maxdepth 1 -type d -name "*#*" -print`;
do
echo "folder is $f"
newFolder=`echo $f | sed 's/#//g'`
echo mv $f $newFolder
mv $f $newFolder
echo newfolder is $newFolder
cd $newFolder
for file in `find . -maxdepth 1 -type f -printf '%f\n'`; do
echo "mv $file to ${newFolder}_$file"
mv $file ${newFolder}_$file
done
cd $curdir
done

Find and gzip files in subdirectories

I have *.xls files in the location /home/Docs/Calc. There are multiple subdirectories inside that folder. Eg
/home/Docs/Calc/2011
/home/Docs/Calc/2012
/home/Docs/Calc/2013
I can gzip each file under the subdirectories using the find command,
find /home/Docs/Calc -iname "*.xls" -exec gzip {} \;
but how can I gzip all the files in each subdirectory ? eg.
/home/Docs/Calc/2011/2011.tar.gz
/home/Docs/Calc/2012/2012.tar.gz
/home/Docs/Calc/2013/2013.tar.gz
I must add that /home/Docs/Calc is one of the many folders eg Calc-work, calc-tax, calc-bills. All of these have the year subfolders in them
Since we don't have to recurse, I'd approach it not with find but with globbing and a for loop. If we're in the Calc directory, echo * will give us all the directory names:
~/Docs/Calc$ echo *
2011 2012 2013
It just so happens that we can use a for loop to iterate over these and tar them up in the usual way:
for year in *; do
tar czf $year.tar.gz $year
done
If you want the resulting tarballs in the year directories, you could add an mv after the tar command. I'd be hesitant to put the tarball in the directory from outset or tar might start trying to tar its own output into itself.
I set up a simple function in my .bashrc:
function gzdp () {
find . -type f -name "$#" -exec gzip {} \;
}
The $# automatically gets replaced with whatever comes after gzdp when you call the function. Now, in your command window you can navigate to the /home/Docs/Calc/ folder and just call:
gzdp *.txt
and it should zip all .txt files in all lower subdirectories.
Not sure if this helps or not, my first post on this website. Careful that you don't accidentally gzip unwanted .txt files.
Try this:
find /home/Docs/Calc -type d -exec tar cvzf {}.tar.gz {} \;
Try this script as well:
#!/bin/bash
find /home/Docs/Calc/ -mindepth 1 -type d | while read -r DIR; do
NAME=${DIR##*/}
pushd "$DIR" >/dev/null && {
tar -cvpzf "${NAME}.tar.gz" *
popd >/dev/null
}
done
You can use the following shell script:
#!/bin/bash
cd /home/Docs/Calc/
find=`find . -type d`
for f in $find; do
cd $f
tar -cvz *.xls >> ${f##*/}.tar.gz
cd -
done

command line bulk rename

I have files in multiple subfolders, I want to move them all to one folder.
Then I like to rename those files.
/foo/A1000-foobar1412.jpg
/foo/A1000-foobar213.jpg
/foo/A1000-foobar314.jpg
/foo1/B1001-foobar113.jpg
/foo2/C1002-foobar1123.jpg
/foo2/C1002-foobar24234.jpg
What I would like to get is:
../bar/A1000-1.jpg
../bar/A1000-2.jpg
../bar/A1000-3.jpg
../bar/B1001-1.jpg
../bar/C1002-1.jpg
../bar/C1002-2.jpg
So what I do so far is:
find . -name "*.jpg" -exec mv {} ../bar/ \;
But now I'm stuck at renaming the files.
Here is a script that just takes the desired basename of the file and appends an incremental index depending on how many files with the same basename already exist in the target dir:
for file in $(find . -name "*.jpg")
do
bn=$(basename $file)
target_name=$(echo $bn | cut -f 1 -d "-")
index=$(($(find ../bar -name "$target_name-*" | wc -l) + 1))
target="${target_name}-${index}.jpg"
echo "Copy $file to ../bar/$target"
# mv $file ../bar/$target
cp $file ../bar/$target
done
With this solution you can't just put an echo in front of the mv to test it out as the code relies on real files in the target dir to compute the index. Instead use cp instead (or rsync) and remove the source files manually as soon as you are happy with the result.
Try this (Not tested):
for file in `find . -name "*.jpg" `
do
x=$(echo $file | sed 's|.*/||;s/-[^0-9]*/-/;s/-\(.\).*\./-\1./')
mv $file ../bar/$x
done

How to copy and rename files in shell script

I have a folder "test" in it there is 20 other folder with different names like A,B ....(actually they are name of people not A, B...) I want to write a shell script that go to each folder like test/A and rename all the .c files with A[1,2..] and copy them to "test" folder. I started like this but I have no idea how to complete it!
#!/bin/sh
for file in `find test/* -name '*.c'`; do mv $file $*; done
Can you help me please?
This code should get you close. I tried to document exactly what I was doing.
It does rely on BASH and the GNU version of find to handle spaces in file names. I tested it on a directory fill of .DOC files, so you'll want to change the extension as well.
#!/bin/bash
V=1
SRC="."
DEST="/tmp"
#The last path we saw -- make it garbage, but not blank. (Or it will break the '[' test command
LPATH="/////"
#Let us find the files we want
find $SRC -iname "*.doc" -print0 | while read -d $'\0' i
do
echo "We found the file name... $i";
#Now, we rip off the off just the file name.
FNAME=$(basename "$i" .doc)
echo "And the basename is $FNAME";
#Now we get the last chunk of the directory
ZPATH=$(dirname "$i" | awk -F'/' '{ print $NF}' )
echo "And the last chunk of the path is... $ZPATH"
# If we are down a new path, then reset our counter.
if [ $LPATH == $ZPATH ]; then
V=1
fi;
LPATH=$ZPATH
# Eat the error message
mkdir $DEST/$ZPATH 2> /dev/null
echo cp \"$i\" \"$DEST/${ZPATH}/${FNAME}${V}\"
cp "$i" "$DEST/${ZPATH}/${FNAME}${V}"
done
#!/bin/bash
## Find folders under test. This assumes you are already where test exists OR give PATH before "test"
folders="$(find test -maxdepth 1 -type d)"
## Look into each folder in $folders and find folder[0-9]*.c file n move them to test folder, right?
for folder in $folders;
do
##Find folder-named-.c files.
leaf_folder="${folder##*/}"
folder_named_c_files="$(find $folder -type f -name "*.c" | grep "${leaf_folder}[0-9]")"
## Move these folder_named_c_files to test folder. basename will hold just the file name.
## Don't know as you didn't mention what name the file to rename to, so tweak mv command acc..
for file in $folder_named_c_files; do basename=$file; mv $file test/$basename; done
done

moving files with folder to new folder in bash

lets say we have something like a bunch of file from
find development/js -name "*.js"
it returns something like
development/js/folder1/*.js
development/js/folder2/*.js
that we need to move to
# as you can see folder 1 & 2 is the same but diffrent folder
production/js/folder1/*.js
production/js/folder2/*.js
how can we move files in bash like above?
thanks!
edit* heres what im upto
#!/bin/bash
devel_file_js=`find ../../development/js -name "*.js"`
production_folder=`../../production/js`
for i in $devel_file_js;
do
mv #hmm
done
Adam Ramadhan
You can do:
#!/bin/bash
dev_folder="../../development/js";
production_folder="../../production/js"
for old_location in $(find $dev_folder -name "*.js")
do
new_location=$(echo ${old_location/${dev_folder}/${production_folder}/})
new_dirname=$(dirname ${new_location})
echo "Moving ${old_location} to ${new_location}"
# Create folder if not exists
if [[ ! -d ${new_dirname} ]]
then
mkdir -p ${new_dirname}
fi
# mv ${old_location} ${new_location}
done
You mean like 'mv' :P
http://linux.about.com/library/cmd/blcmdl1_mv.htm

Resources