perhaps someone can point me in the right direction:
I want to move certain files which are named on a specific type (e.g. file%AA) to the mirrored place in my archive.
So for example i have the following:
livefolder/folder1/file%AA.csv
and want to move it to
archivefolder/folder1/file%AA.csv
When the archive folder does not exist, it should be created.
How can i achive this?
At the moment i am stuck with this:
find /livefolder/folder1/ -type d \( -name '*%AA' \) -exec mv {} /archivefolder/folder1/ +
But then i would need to do this for every subfolder which exist. Is there a way to do this recursevily for all subfolders?
I hope someone can point me in the right direction.
Thanks in advance!
As mentioned in comments by Barmer and Renaud, you can use the rsync. It will create the subdirectories in the path if it does not exist when you use --relative option. But you need to have the parent directory present (unfortunately, in your case archivefolder). Anyways, you can create it with mkdir -p (-p will only create a directory if it does not exist).
rsync command will look like this:
rsync -a --relative livefolder/./folder1/file%AA.csv archivefolder
relative will set the path in destination with respect to the source you have provided.
i.e it will be equal to
rsync [options] livefolder/folder1/file%AA.csv archivefolder/folder1/file%AA.csv
We should use . after livefolder inside the source path in rsync command (rsync -a --relative livefolder/./folder1/file%AA.csv). This means that in the destination path given, rsync will copy in the format /folder1/file%AA.csv (i.e follow the hierarchy mentioned after . in the source). Hence, this will create folder1/file%AA.csv inside archivefolder.
Related
I am trying to move files older than one hour, which are being populated almost every minute very rapidly to another folder whose name specifies the particular hour, in aix.
The script i was trying to run is:
find /log/traces/ -type f -mmin +59 -exec mv '{}' /Directory \;
The above script gives me an error:
find: bad starting directory
I am a newbie to shell scripting.
Any help will be highly appreciated.
------------------Edited-----------------------
I have been able to move the files older than 1 hour, but if the specified folder does not exist, it creates a file with the name specified in command and dumps all the files in it. The script i am running now is:
find /log/traces -type f -mmin +59 -exec mv '{}' /Directory/ABC-$(date +%Y%m%d_%H) \;
It creates a file named ABC-[Current hour]. I want to create a directory and move all the files into it.
If you are not running as a root user you may be getting this problem because of read permissions on /log/traces/.
To see the permission level of this directory run ls -l /log/traces/ the left most column will display something like this drwxr-xr-x which is an explanation of what permission settings that directory has. To understand more read this.
You need to ensure the user you are executing your command as has read access to /log/traces/ - that should fix your error.
Does the directory /Directory- (Timestamp) exist before the script exist? I am guessing the directory is not there to move the files. Make sure the directory exists before you start moving.
You can create a shell script for moving the files that will take the target directory as a parameter along with the file name. Tf the target directory does not exist the script creates the directory. After that script will execute mv command to move the file to the target directory.
Don't bother moving the files, just create them in the right folder directly. How?
Let crontab run each hour and create a dir /Directory/ABC-$(date +%Y%m%d_%H).
And now make a symbolic link between /log/traces and the new directory.
When the link /log/traces already exists, you must replace the link (and not make a link in a subdir).
newdir="/Directory/ABC-$(date +%Y%m%d_%H)"
mkdir -p "${newdir}"
ln -snf "${newdir} /log/traces
The first time you will need to mv /log/traces /log/traces_old and make the first link during a small moment that no new files are created.
Please test first with /log/testtraces first, checking the correct rights for the crontab user.
I have following directory structure :
/home/dir1/abc.jpg
/home/dir1/abc.pdf
/home/dir1/dir2/abc.jpg
/home/dir1/dir2/abc1.jpg
/home/dir1/dir2/dir3/abc.jpg
and I want to copy jpg files from them to a new folder which will have same directory structure, for eg.:
/home/newdir1/abc.jpg
/home/newdir1/dir2/abc.jpg
/home/newdir1/dir2/abc1.jpg
/home/newdir1/dir2/dir3/abc.jpg
How to achieve it using rsync or any other software ?
Please help, Many Thanks !!
From the looks of what you've included in your question, there are a couple of things you might try.
You've specified that you want to "move" files. That means you either use the mv command, or use rsync's --remove-source-files option. For example:
mv /source1/* /source2/* /path/to/targetdir/
or
rsync -a /source1/ /source2/ /path/to/targetdir/
You've no doubt already read the part of rsync's man page that explains the difference between source dirs with and without their trailing slash. If not, read up, because it's important.
If your "thousands of source files [with] similar names" need to be matched from within your source directories, leaving some other files behind, you need to determine whether your "similar names" can be differentiated using pathname expansion or if you should use a regular expression. If the former, then adding the pathname expansion to your sources with either mv or rsync should be sufficient. If you need to use a regex, then find may be a better option:
find /source1/ /source2/ -regex ".*/file[A-F][0-9][0-9].txt" -exec mv "{}" /targetdir/ \;
If these don't solve the problem, then you'll need to supply more detail in your question.
I would try a little shell script like this:
#!/bin/sh
cd /home/dir1
JPEGS=`find . -name "*.jpg"`
tar cf - $JPEGS | (cd /home/newdir1 ; tar xf -)
This first gets the list of all your jpg files with their relative paths, then writes a tar file of them to a pipe into a subshell which changes to the new directory, and then extracts the tar from its stdin.
I thought this would be more of a one liner to be honest.
Pretty simple in notion:
using find on Mac OS X, locate files that meet a criteria, in my case:
all file and directories in a directory:
find ~/Downloads +time1000s
That finds what I need, then I run a conditional, if a dir exists, delete it, if not, create it:
mkdir -p ~/.Trash/safe-to-delte-these-old-files
This means I need to add print0 to my find as files will have spaces, and I want to move, not copy but either way, there is a source, and a destination, and I am getting stuck:
https://gist.github.com/5c0tt/5a2c1fd39ae99d6fca05
Line 27 and 26 seem to cause me issues, I am stuck.
Suggestions on everyone from line 1 to the end. I am trying to hard to do this with POSIX in mind, but i can't even get variables to work then.
It seems BSD does not work the exact same way as other shells and what arguments they accept, which is why I am trying to be more POSIX, as I was told it should run anywhere then.
Thank you.
Took a glance at your git link, a couple of remarks if I may (still a noob tbh so may be irrelevant) :
dir_to_clean="/Users/my_username/Downloads" should probably be dir_to_clean="/Users/$current_user/Downloads" unless you actually have a literal /Users/my_username/Downloads folder.
Instead of cd'ing into your users directory and since you have hardcoded the path to that directory, you could use pushd & popd instead in order to build a stack of directories.
To answer your question, to capture files with spaces in the name for removal you could use something like :
find $dir_to_clean -not -name . +time1000s -exec mv -- {} ~/.Trash/
Could be something like this :
# Initialise variables, user, source to clean, destination
user=$(whoami);
src="/Users/$user/Downloads";
dest="~/.Trash/safe_to_delete";
# Move to directory to clean, not necessary, but if you really want to
pushd $src;
# Check if the destination exists, if not, create it
if [ ! -d $dest ]; then
mkdir -p $dest;
else
echo "destination already exists";
fi
# Find all the file to move then move them
find . -not -name . +time1000s -exec mv -- {} "$dest/" \;
# Return to previous working directory
popd;
pushd the $src directory onto the stack. find all the files in the now current directory ., -not -name . in order to avoid trying to trash the . & .. folders, -- tells find to stop parsing command line options (in cas your file/folder is named i.e. -myfile.txt), exec mv all of the arguments to $dest. popd the still current directory off of the stack. man find (/exec) for more details.
Note : It is also interesting to know that the difference of execution time between the -exec option versus results being piped into xargs can and will often be quite dramatic. Also, if your are actually sure that those files are safe_to_delete, then delete them instead of moving them (-exec rm -- {} $dest/). With all that said, you were correct, one liner.
Further reading :
http://www.softpanorama.org/Tools/Find/using_exec_option_and_xargs_in_find.shtml
I need a script that will find and get me all files in all subdirectories (and leave them in the folder structure as they are now). I know how to find and print that files:
find . -name "something.extension"
The point is, in those directories are lots files that was used before, but I don't want to get those, so the script should only find me files that matches some kind of path pattern which is:
xxx/trunk/xxx/src/main/resources
xxx is different everytime, and after resources there are still some folders that directories are different based on xxx.
Every top xxx folder contains folder named 'tags' (the same level as trunk) that stores previous releases of module (and every release has files that name I am looking for, but I don't want outdated files).
So I want to find all that files in subdirectories of that path pattern that I specified and copy to new location but leave folder structure as it is right now.
I am using Windows and cygwin.
Update
I combined answer commands that 'that other guy' posted below, and it works. Just to be clear I have something like this:
find */trunk/*/src/main/resources -name "something.extension" -exec mkdir -p /absolute/target/path/{} \; -exec cp {} /absolute/target/path/{} \;
Thanks.
Instead of searching under the entire current directory (.), just search under the directories you care about:
find */trunk/*/src/main/resources -name "something.extension"
I have a lot of files named the same, with a directory structure (simplified) like this:
../foo1/bar1/dir/file_1.ps
../foo1/bar2/dir/file_1.ps
../foo2/bar1/dir/file_1.ps
.... and many more
As it is extremely inefficient to view all of those ps files by going to the
respective directory, I'd like to copy all of them into another directory, but include
the name of the first two directories (which are those relevant to my purpose) in the
file name.
I have previously tried like this, but I cannot get which file is from where, as they
are all named consecutively:
#!/bin/bash -xv
cp -v --backup=numbered {} */*/dir/file* ../plots/;
Where ../plots is the folder where I copy them. However, they are now of the form file.ps.~x~ (x is a number) so I get rid of the ".ps.~*~" and leave only the ps extension with:
rename 's/\.ps.~*~//g' *;
rename 's/\~/.ps/g' *;
Then, as the ps files have hundreds of points sometimes and take a long time to open, I just transform them into jpg.
for file in * ; do convert -density 150 -quality 70 "$file" "${file/.ps/}".jpg; done;
This is not really a working bash script as I have to change the directory manually.
I guess the best way to do it is to copy the files form the beginning with the names
of the first two directories incorporated in the copied filename.
How can I do this last thing?
If you just have two levels of directories, you can use
for file in */*/*.ps
do
ln "$file" "${file//\//_}"
done
This goes over each ps file, and hard links them to the current directory with the /s replaced by _. Use cp instead of ln if you intend to edit the files but don't want to update the originals.
For arbitrary directory levels, you can use the bash specific
shopt -s globstar
for file in **/*.ps
do
ln "$file" "${file//\//_}"
done
But are you sure you need to copy them all to one directory? You might be able to open them all with yourreader */*/*.ps, which depending on your reader may let browse through them one by one while still seeing the full path.
You should run a find command and print the names first like
find . -name "file_1.ps" -print
Then iterate over each of them and do a string replacement of / to '-' or any other character like
${filename/\//-}
The general syntax is ${string/substring/replacement}. Then you can copy it to the required directory. The complete script can be written as follows. Haven't tested it (not on linux at the moment), so you might need to tweak the code if you get any syntax error ;)
for filename in `find . -name "file_1.ps" -print`
do
newFileName=${filename/\//-}
cp $filename YourNewDirectory/$newFileName
done
You will need to place the script in the same root directory or change the find command to look for the particular directory if you are placing the above script in some other directory.
References
string manipulation in bash
find man page