8

I have a folder A which has files and directories, I want to move all those files and directories to another folder B, except file, file2, directory, and directory2.

How can this be done?

somethingSomething
  • 5,721
  • 18
  • 58
  • 98

7 Answers7

11

With zsh:

setopt extendedglob # best in ~/.zshrc
mv A/^(file|directory)(|2)(D) B/

(the (D) to include dot (hidden) files).

With bash:

shopt -s extglob dotglob failglob
mv A/!(@(file|directory)?(2)) B/

With ksh93

(FIGNORE='@(.|..|@(file|directory)?(2))'; mv A/* B)
Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
  • I don't even want to think about how much time you must have spent in each shell to learn this! Great answer! – jpaugh Oct 11 '16 at 14:51
10

what i usually do

cd A
ls > a

(assuming you have no 'a' file).

vi a

remove whatever file or directory to be kept in place.

mv $(<a) B
Archemar
  • 31,183
  • 18
  • 69
  • 104
  • Thanks for the answer, I'm thinking some of the experts maybe have some command/"one liner" which is less of a hassle. – somethingSomething Sep 09 '14 at 09:30
  • 1
    It depends, if I have to do it once (my solution) or many time @Falko's solution. – Archemar Sep 09 '14 at 09:35
  • 2
    @somethingSomething This solution allows you to check what you are about to do before you do it. Don't underestimate that. – Ben Sep 09 '14 at 12:54
  • 1
    @Ben, beware though that you have to check that the file names don't contain blank or wildcards or don't start with `-`. You won't be able to spot file names that contain newline characters and it will omit hidden files. – Stéphane Chazelas Sep 09 '14 at 16:03
  • @Ben I see your point. – somethingSomething Sep 09 '14 at 17:12
  • @StéphaneChazelas, 1) if you want to include hidden files just use `ls -a` instead. 2) If you have filenames containing newlines, tabs or nonprintable characters you have bigger problems, and the question should be how to identify and get rid of them. – Ben Sep 09 '14 at 17:48
  • 2
    This can be dangerous for one more reason: if `ls` is an alias to `ls -F` (which is common when not using colors), source paths can have leading `/`, which can have severe side effects - see "Warning" and "Trailing slashes" in `info mv` (or `pinfo mv`, but not in `man mv`) – Volker Siegel Sep 10 '14 at 02:46
5

You can use find with excluded expressions:

find . ! -name . -prune ! -path ./file \
                        ! -path ./file2 \
                        ! -path ./directory \
                        ! -path ./directory2 \
     -exec mv {} your_destination \;

This solution is inspired by this question.

Falko
  • 153
  • 6
  • I get: find: unknown predicate `-E' if I copy and paste your solution, and modify "your_destination" accordingly. – somethingSomething Sep 09 '14 at 09:50
  • 1
    @somethingSomething: I guess you can drop the ```-E``` option. But there might be differences between our systems, since I'm currently on OSX. – Falko Sep 09 '14 at 09:57
2
ls | egrep -v '(file|file2|directory|directory2)' | xargs -i mv {} ../B/
kevino_17
  • 129
  • 1
1

If ./A and ./B are on the same filesystem and if these files do not already exist in ./B:

file file2 directory directory2

...then this operation should just be atomic:

cd ./A; mv * ../B
for mv in file file2 directory directory2
do mv ../B/"$mv" .
done

If they are not, then there are at least 8 additional cross-device copies done with the above set of commands.

mikeserv
  • 57,448
  • 9
  • 113
  • 229
  • Not aware of any shell which guarantees this to truly be atomic. However it should be "really really fast" if its on the same fs. EDIT - that is each mv may be atomic if on the same fs but the entire mv is not atomic – Brandin Sep 09 '14 at 15:26
  • @Brandin - the shell has no involvement in whether or not that is an atomic operation or not. `mv` `unlinks` and `renames` when not crossing devs - it just affects dentries, basically, as i understand it. But the shell doesnt get into that. – mikeserv Sep 09 '14 at 15:40
0

$ sudo mv (source folder name) A B(destination foldername)

ex: create empty dir some sub folder a 1)sudo mkdir -p A/{b/{a,b,c},c,d}

2)ls A/

b c d

3) sudo mkdir B

5)sudo mv a(folder) b(folder)

dhamu
  • 49
  • 1
  • 6
0

You could use a bash array to store which ones you want to skip and then use the containsElement function demonstrated here:

$ skiplist=(file file2 directory directory2)
$ for f in *; do if containsElement "$f" "${skiplist[@]}"; then continue; fi;
mv -v "$f" B; done
Brandin
  • 111
  • 4