How can I move files up a directory where there might be hundreds or thousands of files in the directory, and you might not be sure about whether there are dupes in ... What method would you use?
How to handle dupes will vary, sometimes we’ll overwrite, sometimes we need to be safer. IO can be important because these are production servers. But given quantity a prompt for non duplicate files isn’t an option. Preservation of permissions, and timestamps, etc, is important. We usually won’t know what the data is.
Oh and it using mv isn’t required, rsync, cp solutions welcome.
note: we’re running CentOS 5.5 so let me know if it won’t work there due to it being a more recent… feature
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
I would recommend using rsync from the parent:
rsync -avPr -b --suffix='-original' child/* .
which will backup all existing duplicate files in parent to file-original.
Method 2
cp -bal . ..
This will copy everything in the current directory to the directory above it, retaining all permissions, using hardlinks to minimize IO if possible, and on duplicates it creates filename~
after that
rm -rf . ; cd .. ; rmdir <originaldir>;
Method 3
In this example will move files from ‘/parent/old-dir’ to ‘/parent’:
cd /parent rsync -av --progress old-dir/ . rm -rf old-dir
By rsync rules it will replace dups with newer files from old-dir.
Method 4
You can try
find . -maxdepth 1 -print0 | xargs -I '{}' -r0 mv '{}' ..
which will overwrite dupe files in ..
You can use mv -u ‘{}’ to not overwrite if the dupe in .. is the same or newer
Method 5
mv -i only prompts if the destination exists.
yes n | mv -i … moves all files that don’t exist in the destination directory. On FreeBSD and OSX, you can shorten this to mv -n ….
Note that neither of these will merge a directory argument with an existing directory in the same name in the destination directory.
A separate issue is how to act on all the files in the current directory. There are two problems: grabbing all files (* omits dot files) and not running into a command line . On Linux (or more generally with GNU find and GNU coreutils):
find . -mindepth 1 -maxdepth 1 -exec mv -i -t .. -- {} +
With GNU find but not GNU coreutils (or older GNU coreutils):
find . -mindepth 1 -maxdepth 1 -exec sh -c 'mv -i -- "<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="547014">[email protected]</a>" "$0"' .. {} +
Portably:
find . -name . -o -exec sh -c 'mv -i -- "<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="587c18">[email protected]</a>" "$0"' .. {} -type d -prune
As usual zsh makes things easier. It doesn’t have a command line length limitation internally, so if you use its mv builtin you don’t need to worry about that. And you can tell it not to ignore dot files with the D glob qualifier. Limitation: this doesn’t work across filesystems (as of zsh 4.3.10).
zmodload zsh/files mv -i -- *(D) ..
Method 6
I said on our ML
mv * ..
obviously this isn’t very safe… it will overwrite things. It might have limits that I’ve never run into.
Method 7
The following is a python template that I have used to good effect in the past.
#!/usr/bin/env python
#
# Bart Kastermans, www.bartk.nl
#
# rename of collection of files in a directory
import os
import shutil
# only work on files whose name starts with a D
files = [filename for filename in os.listdir ("/Users/kasterma/Music/Audio Hijack/") if filename[0] =="D"]
for filename in files:
shutil.move (filename, filename [:23] + ".mp3")
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0