Linux - General This Linux forum is for general Linux questions and discussion.
If it is Linux Related and doesn't seem to fit in any other forum then this is the place. |
Notices |
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
Are you new to LinuxQuestions.org? Visit the following links:
Site Howto |
Site FAQ |
Sitemap |
Register Now
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
|
 |
11-26-2005, 04:46 AM
|
#1
|
LQ Newbie
Registered: Aug 2005
Posts: 19
Rep:
|
xcopy functionality with linux?
I need to do a selective and recursive move. the function I am after is done like this in windows:
xcopy c:\music\*.mp3 d:\music\ /s
del *.mp3 /s
I can probably make a script using find and xargs but I thought I would ask first.
I have looked at mmv and unison, (and rsync) none of those are what I am looking for.
rsync is dooable, but it would copy the files and then delete the source, as opposed to simply moving them (And retaining the original inode)
|
|
|
11-26-2005, 05:04 AM
|
#2
|
Senior Member
Registered: May 2003
Location: /var/log/cabin
Distribution: All
Posts: 1,167
Rep:
|
The command to move is mv(move). The command to copy is cp(copy). The command for recursive copying is recursive(-R or -r). The command to delete is rm(remove). The command to delete all subdirectories is force(-f).
cp -R /usr/local/mp3 /home/spackle
mv /usr/local/mp3 /home/spackle
rm -rf /home/spackle/mp3
Last edited by Thoreau; 11-26-2005 at 05:06 AM.
|
|
|
11-26-2005, 05:13 AM
|
#3
|
LQ Newbie
Registered: Aug 2005
Posts: 19
Original Poster
Rep:
|
Quote:
Originally posted by Thoreau
The command to move is mv(move). The command to copy is cp(copy). The command for recursive copying is recursive(-R or -r). The command to delete is rm(remove). The command to delete all subdirectories is force(-f).
|
Thanks, but i already new that much.... you missed the bit about "selective"
say for example i have 10,000 files, and only 1000 end in .txt, how do i *selectively* move those files that end in txt?
|
|
|
11-26-2005, 05:28 AM
|
#4
|
Senior Member
Registered: May 2003
Location: /var/log/cabin
Distribution: All
Posts: 1,167
Rep:
|
mv /usr/local/mp3/*.txt /home/spackle/mp3
|
|
|
11-26-2005, 05:39 AM
|
#5
|
LQ Newbie
Registered: Aug 2005
Posts: 19
Original Poster
Rep:
|
rofl.... ok now you missed the recursive part....
if i have 100s of sub directories then how do i do it? of course many of those directories will contain the files i want to *selectively* *recursively* move...
{EDIT}
http://www.shellscripts.org/project/mvpartial
i found an answer:
#!/bin/bash
if [ $# -ne 3 ] ; then
echo "Usage:"
echo " $0 <sourcedir> <targetdir> <condition>"
echo " Make sure to put the condition into apostrophes to avoid them"
echo " being interpreted by your shell"
echo
echo "Example:"
echo " $0 /usr/src/foo /usr/src/bar 'baz*'"
echo
exit 1
fi
source=${1%/}
target=${2%/}
regex=$3
if [ ! -d "$source" ] ; then
echo "ERROR: $source is not a directory!"
exit 1
fi
if [ ! -d "$target" ] ; then
echo "ERROR: $target is not a directory!"
exit 1
fi
while read file ; do
dirname=$( dirname "$file" )
dirname=${dirname#${source}/}
mkdir -p "${target}/${dirname}"
mv "${file}" "${target}/${dirname}"
done < <( find "$source" -name "$regex" )
Last edited by syssyphus; 11-26-2005 at 07:03 AM.
|
|
|
11-26-2005, 11:51 AM
|
#6
|
Member
Registered: Sep 2005
Location: Old Blighty
Distribution: Slackware, NetBSD
Posts: 536
Rep:
|
Quote:
say for example i have 10,000 files, and only 1000 end in .txt, how do i *selectively* move those files that end in txt?
|
If you used a proper shell like zsh, you could just do
Code:
mv /src/path/**/*.txt /dest/path
No need for any scripts.
|
|
|
11-26-2005, 01:58 PM
|
#7
|
LQ Newbie
Registered: Aug 2005
Posts: 19
Original Poster
Rep:
|
oh very nice, thank you... we are almost there =)
the zsh recursive globing works, but if does not retain the original directory hierarchy
example:
[ew@client01]~/raid% find source
source
source/test.txt
source/2ndlevel
source/2ndlevel/test.txt
[ew@client01]~/raid% mv source/**/*.txt dest/
mv: will not overwrite just-created `dest/test.txt' with `source/test.txt'
Last edited by syssyphus; 11-26-2005 at 01:59 PM.
|
|
|
11-26-2005, 02:33 PM
|
#8
|
Member
Registered: Sep 2005
Location: Old Blighty
Distribution: Slackware, NetBSD
Posts: 536
Rep:
|
Quote:
the zsh recursive globing works, but if does not retain the original directory hierarchy
|
Aha, what you are looking for is the magic of the zmv function (have a look at /usr/share/zsh/<version>/functions/zmv, it is well documented).
Code:
zmv -p mvmkdir -w '/src/path/**/*.txt' /dest/path/'$1$2'
where mvmkdir is a function/script to ensure that the directory exists:
Code:
mvmkdir() { [[ ! -d $3 ]] && mkdir $3 && mv $@; }
EDIT:
Bugger, ignore the above mvmkdir function -- brain cramp. This should be correct:
Code:
mvmkdir()
{
local dir=$3:h
[[ -e $dir && ! -d $dir ]] return 1
[[ ! -d $dir ]] && mkdir -p $dir
mv $@
}
Last edited by ioerror; 11-27-2005 at 08:20 AM.
|
|
|
11-26-2005, 02:35 PM
|
#9
|
LQ Newbie
Registered: Nov 2005
Posts: 8
Rep:
|
|
|
|
11-26-2005, 03:10 PM
|
#10
|
LQ Newbie
Registered: Nov 2005
Posts: 2
Rep:
|
re: xcopy & del ->
Well, close but no cigar so far. I had to test xcopy to see that the 'globbing' (incorrectly from a logic standpoint) did as the original post suggested. The delete command in windows also does the logically fallacious same thing.
To selectively copy, recursively in unix, there is NOT a single hybrid command that accomplishes such. BUT, the beauty of unix is that the toolkit is robust. Break the job into smaller parts.
First, identify the files that need copying.
Then select those files (that is what 'globbing' short-cuts - combining these two issues.)
Then, MOVE them, rather than copying, so that no subsequent 'del' is required.
HOWEVER: The most robust manner to copy files from location A to location B in Unix is the old standby 'tar'.
The most robust manner of identifying files, recursively, is find.
The easiest manner of simulating globbing (ie. wildcard matching) is to use pattern matching - eg. patterns in grep/egrep/fgrep.
(Pattern matching is far more powerful than globbing.)
Avoid globbing with 'thousands of files' and 'hundreds of directories'. Your shell can go belly up. Csh used to have a limit of around 500,000 bytes being matched by globbing, bsh was well over 1,000,000 bytes. Always a difficult limitation to identify, unless one is familiar with it. Not to mention, that 'globbing' that much is extremely slow. Base level unix tools are much more efficient, and tool pattern matching is much more efficient, and flexible than shell globbing.
Method 1:
cd c:/mp3
find . > /tmp/t0
egrep '\.mp3$' /tmp/t0 > /tmp/t1
tar -cf `cat /tmp/t1` | ( cd d:/newdirectory ; tar -xf - )
rm -i /tmp/t0 /tmp/t1 # clean-up one's cruft
# Finished - note - the above is 'overkill' - and ONLY covers the 'xcopy' equiv.
# The detail was provided above so that the following equivs might make sense, as to method.
On one line - the 'xcopy' equiv:
musicfiend> cd c:/mp3 ; tar -cf - `find . | grep '\.[Mm][Pp]3$'` | ( cd d:/newdirectory ; tar -xf - )
On one line - the 'del' equiv (complete with verification of every single file to be removed *s* )
musicfiend> rm -i `find c:/mp3 | grep '\.[Mm][Pp]3$'`
AVOID LIKE THE PLAGUE EVER, EVER, EVER using the 'recursive' flag on rm.
It will eventually nail you, big time. ( The -i flag is overkill - use Method 1 with the file list cat for sure fire safe removal of the files. It gives you a file to be examined first.)
Safer, faster, more precise control in Unix.
Yes, SEEMINGLY more complex, but not really. The 'combining principles' are the same for ALL shells and ALL tools - allowing the same basic 'custom' design to be used for a multitude of solutions and combinations via different tools.
Attitude difference: Tiny tools to build complex, extremely flexible solutions (tar excluded from tiny and uncomplex),
or complex tools with zillions of options, and very specific, inflexible usage.
Just my opinion from the soap box.
|
|
|
11-26-2005, 03:21 PM
|
#11
|
LQ Newbie
Registered: Nov 2005
Posts: 8
Rep:
|
Re: re: xcopy & del ->
I just put a short perl wrapper around File::Xcopy in 'xcopy' in /user/local/bin, and now have xcopy for bash.
Quote:
Originally posted by DConfusion
I had to test xcopy to see that the 'globbing' (incorrectly from a logic standpoint) did as the original post suggested. The delete command in windows also does the logically fallacious same thing.
|
Hmm... I guess I could stick File::DosGlob in there.
*will stop perl advocacy now* :-D
|
|
|
11-26-2005, 03:44 PM
|
#12
|
LQ Newbie
Registered: Nov 2005
Posts: 2
Rep:
|
Re: perl advocacy
LOL -
Yes, one can do it that way.
Another Unix axiom - from Larry, I believe.
There is no single right way to do anything in Unix.
I prefer the 'basic' tool kit approach, and really never, ever wish to 'duplicate' dos tools. *w*
Although a perl twinkie myself, some tasks are better done with simplicity. I use perl (started as a bsh script) for an extensive, exhaustive, robust clean up between two semi-duplicated directories. I have never found anything that really comes close to it in dos - and have looked at several dozen so-called 'synchronizing' or 'cleanup' programs. None of them really do the job properly, nor robustly. BUT - the perl script still goes down to the shell tool level for safety (sacrifice some speed). Perl handles all the book keeping, which it does beautifully.
The small tool approach I outlined will work from the command line of even the most basic of installs - ie. a stripped down system. Most of those tools are de rigour in even a base level install.
That said - I like your style, and appreciate the work you have done.
|
|
|
11-27-2005, 01:24 PM
|
#13
|
Member
Registered: May 2005
Posts: 378
Rep:
|
To copy selected files use cpio:
Code:
find /blah -name "*.txt" -print | cpio -pvdum /target/dir
You don't have to resort to using an incompatible shell (zsh) to do something this simple.
|
|
|
All times are GMT -5. The time now is 08:42 AM.
|
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.
|
Latest Threads
LQ News
|
|