Moving files to a directory - bash

I want to move all files matching a certain pattern in the current directory to another directory.
For example, how would I move all the files starting with nz to a directory called foobar? I tried using mv for that, but it didn't work out well.

find . | grep "your_pattern" | xargs mv destination_directory
Does the following:
Finds all files in the current directory
Filters them according to your pattern
Moves all resulting files to the destination directory

mv nz* foobar should do it.

mv nz* foobar/

Try to use "mmv", which is installed on most Linux distros.

This will do it, though if you have any directories beginning with nz it will move those too.
for files in nz*
do
mv $files foobar
done
Edit: As shown above this totally over the top. However, for more complex pattern matches you might do something like:
for files in `ls | grep [regexp]`
do
mv $files foobar
done

mv nz* foobar/
mv - will move or rename file
nz - will get all the items that start with the "nz"
foobar/ - is the directory where all items will go into

Related

Deleting specific files in a directory using bash

I have a txt file with a list of files (approximately 500) for example:
file_0_hard.msOut
file_1_hard.msOut
file_10_hard.msOut
.
.
.
file_1000_hard.msOut
I want to delete all those files whose name is not in the txt file. All of these files are in the same directory. How can I do this using bash where I read the text file and then delete all those files in the directory that are not in the text file. Help would be appreciated.
Along the lines of user1934428
There is something to say for this solution. But since we have linux at our disposal with a strong filesystem in use I hope. we can make hardlinks; The only requirement for that the destination is on the same filesystem.
So along those lines:
make a directory to store the files you want to keep.
hardlink (ln {file} {target}) ; as this does not cost extra disk space, it only stores the inode number in the new directory file.
remove all files
move the files back from their origin.
And actually this would be about the same as:
mv {files} {save spot}
remove all files
mv {save spot}/{files} back
Which does pretty much the same thing. Then again; it is a nice way to learn about the power of a hardlink.
you may try this :
cd path/dir
for f in *; do
if ! grep -Fxq "$f" pathToFile/file.txt; then
rm -r "$f"
else
printf "exists-- %s \n" ${f}
fi
done
In case you are wondering (as I did) what -Fxq means in plain English:
F: Affects how PATTERN is interpreted (fixed string instead of a regex)
x: Match whole line
q: Shhhhh... minimal printing
Assuming the directory in question is mydir
set -e
cd mydir
tmpdir=/tmp/x$$ # adapt this to your taste
mv $(<list.txt) $tmpdir
cd ..
rm -r mydir
mkdir mydir
mv $tmpdir/* mydir
rm -r $tmpdir
Basically, instead to delete those files you want to keep, you safe them, then delete everything, and then restore them. For your case, this is probably faster than doing the other way around.
UPDATE:
As Michiel commented, it is advisable that you place your tmpdir in the same file system as mydir.

Unable to rename and move files from one location to another

I need to add prefix C_ and then move files from tmp location to target location.
Here is the script
I am not allowed to place script in current directory.
for tmpfile in /home/asmita/tmp
do
mv "$tmpfile" "C_${tmpfile}"
mv "C_${tmpfile}" /home/tgasmita
done
When I try moving prefixed files I get error C_/home/asmita/tmp/xyz.txt not found. as entire path is stored in tmpfile variable.
Change your code to use the basename and the dirname command to get the filename and the directory name. Use these to combine the values and get the new path.
for tmpfile in /home/asmita/tmp
do
DIRPATH=$(dirname "${tmpfile}")
FILENAME=$(basename "${tmpfile}")
mv "$tmpfile" "${DIRPATH}C_${FILENAME}"
mv "${DIRPATH}C_${FILENAME}" /home/tgasmita
done
There are many ways to do this. First let me fix your script.
1.In below code make sure that you are passing only filename not the full path. Below script is valid only if know the FILENAME
#!/bin/sh
for tmpfile in /home/asmita/tmp
do
mv "{tmpfile}/filename.txt" "/home/tgasmita/C_filename.txt"
done
2.If you do not know file name and you want to rename and move .txt files to another folder then you might like below script.
#!/bin/sh
lines=`find /home/asmita/tmp -name "*.txt" -printf "%f\n";`
for i in ${lines[#]}
do
mv "/home/asmita/tmp/${i}" "/home/tgasmita/C_${i}"
done
Please note that I m looking for only text file in source folder(/home/asmita/tmp
) You can change .txt to other extension according to requirement. If you want to move and rename all files from source folder then just replace "*.txt" to ".*" from second line.

batch renaming of multiple files of same extension

I need to rename multiple files without knowing the filename(basename/string name ) of the file.
i tried with:
for i in $(ls /Users/Destiny/Desktop/Index/*.ebwt);
do
mv -v "$i" "${i/hsa/hsa.genome.V86C}"; ## works when i know the string to replace
done
but what if dont know the filename(string name)?
Before rename: hsa.1.ebwt hsa.2.ebwt hsa.3.ebwt hsa.4.ebwt
After rename: hsa.genome.V86C.1.ebwt hsa.genome.V86C.2.ebwt hsa.genome.V86C.3.ebwt hsa.genome.V86C.4.ebwt
You could do something with a find in your directory. And if they all have the same extension then it could be something like below with your move that you currently have:
find /Users/Destiny/Desktop/Index -type f -name "*.ebwt" | while read file;
do
mv -v "$file" "${file/hsa/hsa.genome.V86C}";
done
This will rename it inside of the current directory, and if you want to move it to a different directory later down the line, you could surround second argument like this with basename to make moving easier:
"/SomeDirectory/$(basename ${file/hsa/hsa.genome.V86C})"
You could also put a -maxdepth 1 after the directory you want to find if you dont want it to be recursive in the find

Do actions in each folder from current directory via terminal

I'm trying to run a series of commands on a list of files in multiple directories located directly under the current branch.
An example hierarchy is as follows:
/tmp
|-1
| |-a.txt
| |-b.txt
| |-c.txt
|-2
| |-a.txt
| |-b.txt
| |-c.txt
From the /tmp directory I'm sitting at my prompt and I'm trying to run a command against the a.txt file by renaming it to d.txt.
How do I get it to go into each directory and rename the file? I've tried the following and it won't work:
for i in ./*; do
mv "$i" $"(echo $i | sed -e 's/a.txt/d.txt/')"
done
It just doesn't jump into each directory. I've also tried to get it to create files for me, or folders under each hierarchy from the current directory just 1 folder deep, but it won't work using this:
for x in ./; do
mkdir -p cats
done
OR
for x in ./; do
touch $x/cats.txt
done
Any ideas ?
Place the below script in your base directory
#!/bin/bash
# Move 'a.txt's to 'd.txt's recursively
mover()
{
CUR_DIR=$(dirname "$1")
mv "$1" "$CUR_DIR/d.txt"
}
export -f mover
find . -type f -name "a.txt" -exec bash -c 'mover "$0"' {} \;
and execute it.
Note:
If you wish be a bit more innovative and generalize the script, you could accept directory name to search for as a parameter to the script and pass the directory name to find
> for i in ./*; do
As per your own description, this will assign ./1 and then ./2 to i. Neither of those matches any of the actual files. You want
for i in ./*/*; do
As a further aside, the shell is perfectly capable of replacing simple strings using glob patterns. This also coincidentally fixes the problem with not quoting $i when you echo it.
mv "$i" "${i%/a.txt}/d.txt"

Automatically move folders based on file name?

I have about 1500 folders that I need to organize automatically via command line.
I'm looking for a way to search for all folders that contain /lib/file.php - if file.php does exist in the lib folder, I need the root folder (one level above lib) move into a new directory.
I know how to search for all folders containing /lib/file.php but can't figure out how to move them automatically into a new folder. For example, if /test123/lib/file.php exists, then the test123 folder should be moved into a new folder...
Try using pipe chain of find, sed, xargs and mv
find -type f -wholename '*/lib/file.php' | sed 's:/lib/file\.php$::' | xargs -I dirs mv dirs /path/to/new/dir/
Something like this, maybe:
for d in *
do
if [[ -r "${d}/lib/file.php" ]]
then
mv "${d}" "/some/new/place/."
fi
done

Resources