1

I'm trying to learn bash on Linux, just for fun. I thought it would be pretty useful to have a .sh that would group together similar files. For example, let's say we have the directory

/home/docs/

Inside the directory we have /mathdocs/, /codingdocs/, etc.

Inside those sub-directories we have doc.txt, in all of them. Same name for all the files on the subdirectories.

Let's say I want to group them together, and I want to move all the files to /home/allthedocs/ and rename them after the directories they were in. (mathdocs.txt, codingdocs.txt, etc.)

How could I do that?

I've tried to create a script based on the ls and cp commmands, but I don't know how I can take the name of the directories to rename the files in it after I moved them. I guess it has to be some sort of iterative sentence (for X on Y directories) but I don't know how to do it.

codeforester
  • 39,467
  • 16
  • 112
  • 140
DRZN93
  • 13
  • 3
  • Check this post - it is almost same as your question: https://stackoverflow.com/questions/44460177/copying-files-from-multiple-directories-into-a-destination-directory – codeforester Jun 11 '17 at 21:04
  • Possible duplicate of [Getting the source directory of a Bash script from within](https://stackoverflow.com/questions/59895/getting-the-source-directory-of-a-bash-script-from-within) – galkin Jun 11 '17 at 21:06
  • 1
    @galkin pretty sure it's not a duplicate of that. – 123 Jun 11 '17 at 21:14

2 Answers2

0

You can move and rename your file in one shot with mv, with a loop that grabs all your files through a glob:

#!/bin/bash

dest_dir=/home/allthedocs

cd /home/docs
for file in */doc.txt; do
  [[ -f "$file" ]] || continue # skip if not a regular file
  dir="${file%/*}"             # get the dir name from path
  mv "$file" "$dest_dir/$dir.txt"
done

See this post for more info:

codeforester
  • 39,467
  • 16
  • 112
  • 140
0

Here is a one liner solution that treats whitespaces in filenames, just as @codeforester 's solution does with the glob.

Note that white spaces are treated with the "-print0" option passed to "find", the internal field separator (IFS) in while loop and the wrapping of file3 variable with quotes.

The parameter substitution from file2 into file3 gets rid of the leading "./".

The parameter substition inside the move command turns the path into a filename (run under /home/docs/):

find . -maxdepth 2 -mindepth 2 -print0 | while IFS= read -r -d '' file; \
do file2=$(printf '%s\n' "$file"); file3=${file2#*\/*}; \
mv "$file2" ../allsil/"${file3//\//}"; done
Serhat Cevikel
  • 720
  • 3
  • 11
  • The glob based solution works for files with whitespaces. `find` is not really needed because both directory hierarchy and file names (doc.txt) are fixed. – codeforester Jun 11 '17 at 22:49