6

I have a folder called home/homeLife

I have a file called home1 home2 and home3 stored in /home

I want to move all files that start with home* to home/homeLife/..

I typed

mv home* /home/homeLife
cannot move homeLife into subdirectory of itself

My question: How can I exclude directories?

  • 2
    Do you have a file called home1 home2 and home3 or files called home1, home2, home3? – heemayl Mar 9 '15 at 16:50
  • 1
    I gave an answer below to solve your task. The question to exclude directories is a bit less simple; I propose to use the find -type f command. (I'll provide details on request if necessary.) – Janis Mar 9 '15 at 16:54
  • 2
    regardless of the error message, your command should have succeed; it skipped the directory homeLife, because, at it says, it cannot move homeLife into itself. – drs Mar 9 '15 at 16:54
  • heemay- No. I just made them with touch. I am working on a book called The Linux Command Line. They are empty files. Sometimes I just make up random tasks to learn things. – Michael Bruce Mar 9 '15 at 18:00
  • Hmm... i did not check yet if it, in fact did perform the move. Ill look immediately. Janis. Yes. I would like more details. I am all about understanding Linux. Thank you for the command find -type f – Michael Bruce Mar 9 '15 at 18:03
8

With zsh, use glob qualifiers:

mv home*(.) dst 

moves only regular files.

While

mv home*(^/) dst 

moves files of any type except directories.

mv home*(^-/) dst

would also exclude symlinks to directories.

  • echo $SHELL shows zsh... I didn't realize I was using that. (NEWB). Anyway your commands are perfect. I deleted all files in a current working dir with # rm *(.) thanks again! – Michael Bruce Mar 9 '15 at 18:31
4

You can use find. The following should work.

find . -name home\* -type f -maxdepth 1 -exec mv {} /home/homeLife/. \;
  • I am amazed at how many ways this mv function can be manipulated. – Michael Bruce Mar 10 '15 at 18:18
  • I am curious to what the "\*" is for? Why not just "home*" ? – Michael Bruce Mar 10 '15 at 18:47
  • In my example above, I am using '\' to avoid shell interpreting the wildcard. Quoting your wildcard like "home*" will work as well. – Arul Selvan Mar 10 '15 at 22:19
2

You're close already. To move your files home1, home2, home3 use the globbing pattern home?.

mv home? /home/homeLife/

The ? denotes any single character, while the * denotes any amount of characters (including none).

  • One point, if the file name really is home1 home2 and home3 then you better use mv home?* /home/homeLife/ ..this will work for both circumstances.. – heemayl Mar 9 '15 at 17:13
  • 1
    heemayl, that will not address the issue since your pattern will also match homeLife which was the one to avoid with the globbing expression. – Janis Mar 9 '15 at 17:17
  • my bad..did not see it closely.. :) – heemayl Mar 9 '15 at 17:18
2

You can use bash extended globs:

shopt -s extglob                ## activate extglogs if not yet done
mv  home!(*Life) homeLife/      ## !(p1|...) = anything except one of the patt
2

Portably you can prune your glob match list:

set --; cd /home
for f in ./home*
do  [ ! -L "$f" ] && 
      [ -f "$f" ] && 
      set "$@" "$f"
done
[ "$#" -eq 0 ] || mv "$@" ./homeLife
  • +1 for portability (there are a lot of very old systems out there!) – Olivier Dulac Mar 10 '15 at 12:52
  • Note that it moves regular files and symlinks to regular files. – Stéphane Chazelas Mar 10 '15 at 12:59
  • @StéphaneChazelas - is that what you were talking about? Weird that mv doesn't seem to have any -LHP switches spec'd. – mikeserv Mar 10 '15 at 13:09
  • [ -f "$f" ] of [ ! -d "$f" ] were possibly fine for the OP. It's just worth noting that those tests (as opposed to find's -type or zsh's *(.), *(^/) for instance) look at the type after resolving symlinks. mv renames directory entries, -LHP would not be relevant for it. – Stéphane Chazelas Mar 10 '15 at 13:37
0

Of course, if you had only 3 files, you could just do

 mv home1 home2 home3 homeLife

Sometimes it is easier to do things manually than read the documentation. If you really had a large number of files named home*, then one trick that I use (that is now part of bash) is to expand all the glob matches and then manually delete the matches I don't want. To expand a glob, type Ctrl+x * after you type the glob expression. It will expand on the command line, and then you manually fix it.

For example, in my directory, I have a lot of "test" files and I want to cat all of them besides test2 to a new file:

cat test*

Now type Ctrl+x *, and it expands to

cat test test10 test11 test12 test13 test14 test15 test16 test17 test2 test20 test21 test22 test23 test24 test25 test26 test27 test28 test29 test3 test30 test31 test32 test33 test34 test35 test36 test37 test38 test4 test5 test6 test7 test8 test9 testa testb testbuild testc testd teste testf

Then cursor back and remove test2 with 5 backspaces, and then add > test_all to the end of the command line.

cat test test10 test11 test12 test13 test14 test15 test16 test17 test20 test21 test22 test23 test24 test25 test26 test27 test28 test29 test3 test30 test31 test32 test33 test34 test35 test36 test37 test38 test4 test5 test6 test7 test8 test9 testa testb testbuild testc testd teste testf > test_all

There are a bunch of other features of Ctrl+x, but this is the only one I remember.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.