10

I don't have to move the folders, only the files.

I have tried mv * but this command moves the folders also.

6 Answers 6

14

If you want to move everything except directories from $SOURCE_DIR to $TARGET_DIR, you can use this command:

find "$SOURCE_DIR" -maxdepth 1 -not -type d -exec mv -t "$TARGET_DIR" -- '{}' +

Explained in detail:

  • find: The find search for files in a directory
  • $SOURCE_DIR: The directory to search in
  • -maxdepth 1: Do not look inside subdirectories
  • -not -type d: Ignore directories
    • You could also use -type f if you only want to copy things that are strictly files, but I prefer the above because it also catches everything that's neither a file nor a directory (in particular symbolic links)
  • -exec mv -t "$TARGET_DIR" -- '{}' +: Run the command mv -t "$TARGET_DIR" -- FILES... where FILES... are all the matching files (thanks @DavidFoerster)
2
  • 2
    find ... -exec mv -t "$TARGET_DIR" -- '{}' + would be safer (in case $TARGET_DIR is no directory or the match starts with -) and more efficient (because it doesn't spawn a new sub-process for every matched file). Apr 1, 2017 at 12:50
  • @DavidFoerster Thanks, updated (also learnt something new today!)
    – Frxstrem
    Apr 1, 2017 at 13:36
5

I think you want to mv only your files.First go to the your directory and use this command, replace $TARGET with your target directory path. If you want to copy your files replace mv with cp.

find . -type f -exec mv {} $TARGET \;

if I explain this, find . -type f means select all files and -exec mv {} $TARGET \; means execute mv command to all selected items.


Previous answer has a error.. it mv all files inside sub directories also. The quick fix is use -maxdepth 1. Then it not recursively mv files within sub directories. Below is the correct one..

find . -maxdepth 1 -type f -exec mv {} $TARGET \;
2
  • I don't think the questioner wants this! It would also move all files in any subdirectories into that same target directory. The -type f doesn't prevent recursion. Apr 1, 2017 at 11:30
  • @MartinThornton thank you for your suggestion.. i will edit my answer... Apr 1, 2017 at 11:44
4

If you're using zsh instead of bash, you can do this:

mv "$SOURCE"/*(.) "$TARGET"

The (.) at the end is called a glob qualifier; the . inside specifically means to only match regular files.

Doing a mv *(.) "$target" is quick and practical. However, if you're doing this as part of a script, you might want to consider instead writing something like what Frxstrem and David Forester suggested, mv -t "$target" -- *(.), to better handle corner cases that might arise in other people's usage.

1
  • 1
    As David Forester pointed out on my answer, mv -t "$TARGET" -- "$SOURCE"/*(.) would be safer (in case "$TARGET" starts with a - or is not a directory). I do like the zsh solution though!
    – Frxstrem
    Apr 1, 2017 at 22:19
3

Python approach

When dealing with files recursively, find is the way to go. In this particular case it's not necessary, but can be used with -maxdepth 1 as other answers show.

Simple python command can do it as well. Here's an example:

$ tree
.
├── a_directory
└── a_file

$ python -c "import os,shutil;fl=[f for f in os.listdir('.') if os.path.isfile(f)];                                      
> map(lambda x:shutil.move(x,'./a_directory'),fl)"

$ tree
.
└── a_directory
    └── a_file

1 directory, 1 file

How this works:

  • fl=[f for f in os.listdir('.') if os.path.isfile(f)] iterates over all items that os.listdir('.') finds and we test whether the item is a file using os.path.isfile() function.

  • Once fl file list is built, we use map() function. This function takes two arguments - a function, and a list of items; it will perform the function that we gave it per each file in a list. Thus here we havelambda x:shutil.move(x,'./a_directory') as anonymous function which will move a a given file to a given directory, and then we have the fl - the list of files that we built up.

For readability and general usage, we could also rewrite this as a general python script, which takes two arguments - source directory and destination subdirectory.

#!/usr/bin/env python3
from os import listdir
from os.path import isfile,realpath
from os.path import join as joinpath
from shutil import move
from sys import argv

# this is script's full path
script=realpath(__file__)
# get all items in a given directory as list of full paths
fl=[ joinpath(argv[1],f) for f in listdir(argv[1]) ] 
# filter out script itself ( just in case) and directories
fl_filtered = [ f for f in fl if isfile(f) and not script == realpath(f) ]
# Uncomment this in case you want to see the list of files to be moved
# print(fl_filtered)
# move the list of files to the given destination
for i in fl_filtered:
     move(i,argv[2])

And the usage is like so:

$ tree
.
├── a_directory
├── a_file
└── files2subdir.py

1 directory, 2 files

# Notice: the script produces no output unless you uncomment print statement
$ ./files2subdir.py "." "./a_directory"                                                                                  

$ tree
.
├── a_directory
│   └── a_file
└── files2subdir.py
1
2

To move everything except directories from source-dir directory to destination-dir directory, in Python:

#!/usr/bin/env python3
"""Usage: mv-files <source-dir> <destination-dir>"""
import shutil
import sys
from pathlib import Path

if len(sys.argv) != 3:
    sys.exit(__doc__)  # print usage & exit 1
src_dir, dest_dir = map(Path, sys.argv[1:])
for path in src_dir.iterdir():
    if not path.is_dir():
        shutil.move(str(path), str(dest_dir / path.name))

See Running Python File in Terminal.

3
  • @SergiyKolodyazhnyy I don't see such requirement in pep-8 and (according to the example there) it is actually the exact opposite: import mypackage before from mypackage import ...
    – jfs
    Apr 2, 2017 at 22:41
  • @SergiyKolodyazhnyy don't confuse the special from __future__ imports and ordinary from pathlib imports.
    – jfs
    Apr 3, 2017 at 4:30
  • Yeah, looks like I've misread that part. No, you're right, import module should be first (which is library and third party imports) from module import object should be last ( local/library specific) Apr 3, 2017 at 4:53
0

I'd use

mv *.*

this will work as long as your folders don't have extensions.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .