13

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?

5
  • 2
    Do you have a file called home1 home2 and home3 or files called home1, home2, home3?
    – heemayl
    Mar 9, 2015 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, 2015 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, 2015 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. Mar 9, 2015 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 Mar 9, 2015 at 18:03

6 Answers 6

10

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.

1
  • 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! Mar 9, 2015 at 18:31
5

You can use find. The following should work.

find . -name home\* -type f -maxdepth 1 -exec mv {} /home/homeLife/. \;
3
  • I am curious to what the "\*" is for? Why not just "home*" ? Mar 10, 2015 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
    Mar 10, 2015 at 22:19
  • The -maxdepth 1 option needs to come first, otherwise find will issue a warning. Sep 6, 2019 at 21:08
3

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
0
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).

3
  • 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, 2015 at 17:13
  • 2
    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, 2015 at 17:17
  • my bad..did not see it closely.. :)
    – heemayl
    Mar 9, 2015 at 17:18
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
4
  • +1 for portability (there are a lot of very old systems out there!) Mar 10, 2015 at 12:52
  • Note that it moves regular files and symlinks to regular files. Mar 10, 2015 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, 2015 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. Mar 10, 2015 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.