0

I've been trying to find a way to free up some space on a drive by moving folders to another. I have a folder full of stuff I can move, doesn't need to be all of it, to free up some space.

In Windows I'd just select a bunch of folders, get the properties, it'd tell me how much space it was taking up, I'd select more or less and then move them. I can't do that from a bash terminal, and I have no idea how to go about it. Google searching keeps leading me down the path of moving all files over a certain size, which isn't what I'm trying to do.

1

On a GNU system, you could script it as:

#! /bin/bash -
usage() {
  printf >&2 '%s\n' "Usage: $0 <destination> <size> [<file1> [<file2>...]]"
  exit 1
}
(($# >= 2)) || usage
dest=$1
size=$(numfmt --from=iec <<< "$2") || usage
shift 2
(($# == 0)) && exit
selected=()
sum=0

shopt -s lastpipe
LC_ALL=C du -s --null --block-size=1 -- "$@" |
  while
    ((sum < size)) &&
      IFS= read -rd '' rec &&
      s=${rec%%$'\t'*} &&
      file=${rec#*$'\t'}
  do
      selected+=("$file")
      ((sum += s))
  done

((${#selected[@]} == 0)) ||
  exec mv -t "$dest" -- "${selected[@]}"

Used for instance as:

that-script /dest/folder 1G *

To move as many files as necessary from the expansion of that * glob to make up at least 1GiB.

  • This looks like exactly what I'm after, but I'm getting du: write error. It's doing the job, but is that error avoidable? – Tod Jan 29 at 15:55
  • @Tod, I can't reproduce it. What operating system are you using? You can always redirect all the errors of du to /dev/null (du 2> /dev/null instead of du). – Stéphane Chazelas Jan 29 at 16:51
  • @Tod, I can reproduce with older versions of GNU du but only if I ignore the SIGPIPE signal (as in (trap '' PIPE; du -s /bin/*) | head -n 1). SIGPIPE should not be ignored under normal conditions though. what do you get if you run grep SigIgn /proc/self/status? – Stéphane Chazelas Jan 29 at 16:55
  • I'm using Slackware 14.2. the result of that command: SigIgn: 0000000000001000 – Tod Jan 30 at 8:33
  • @Tod, yes, it seems you have SIGPIPE ignored, which is wrong. It would be worth investigating how you ended up in that situation. – Stéphane Chazelas Jan 30 at 9:19
1

You could pretty much do the exact same thing within the terminal:

First execute cd /path/to/full/drive/ to get into the filled up drive's root folder.

Then, to view the capacity taken by each folder inside that drive you could use du -hd1 (assuming the GNU implementation of du).

Explanation: du (Disk Usage) runs recursively on your file tree from current folder, printing the capacity used by each folder. By default it's printed as number of 512-byte units or kibibytes (depending on whether POSIXLY_CORRECT is in the environment which is somewhat unreadable), and so the -h option tells it to print sizes as "human readable" (converted to MB/GB). The d parameter forces du to stop its descent into the file tree after reaching the specified "depth" (in this case 1).

Once you find a specific directory you'd like to move content from you could use ls -lh to view file sizes inside this directory to identify specific files to move. Here the h is once again for printing sizes as "human readable", and -l is to get the "long" format which includes file sizes.

Bonus point: You could pipe du into sort (here again assuming GNU sort) to get the output sorted by size (assuming the file names don't contain newline characters) to make things easier like so:

du -hd1 | sort -h

and ls can sort the output by size as well when providing the -S option:

ls -lhrS

Finally, to move files/folders you can use the mv /path/to/source /path/to/target command.

I'm assuming that you know what is the root folder of the relevant drive.

  • 1
    On Linux, and some other Unices, ls -lS will sort by size. Your pipeline ls -lh | sort -h would not sort by size. – Kusalananda Jan 29 at 10:01
  • 1
    @Kusalananda, ls -S is now POSIX. ls -h is not (neither are du -h, nor du -d1 all GNU extensions, nothing to do with Linux). – Stéphane Chazelas Jan 29 at 10:07
  • @StéphaneChazelas Ah, ls -S is POSIX. I'm not keeping updated. – Kusalananda Jan 29 at 10:09
0

Use du -hd1

-h prints size in human readable format

-d <1> is the depth for directory.

Example:

$ du -hd1 
11G     ./dir1
9.5G.   ./dir2
11G     ./dir3
6.3G    ./dir4
9.1G    ./dir5
6.4G    ./dir6
4.8G    ./dir7 
58G     .

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.