find /hosted -maxdepth 1 -name "partner*" -type d | while read -r dir
do
cp "${dir}/logo.png" "/partners/$(basename ${dir}).png"
done
Or
find /hosted -maxdepth 1 -name "partner*" -type d | while read -r dir
do
cp "${dir}/logo.png" "/partners/${dir##*/}.png"
done
First of all, it is never a good idea to parse the output of ls
since it can lead to all sorts of problems. A better way to get the age of a file is stat
. For example:
$ ls -l 20120322222.log
-rw-r--r-- 1 terdon terdon 0 Jan 1 2012 20120322222.log
$ stat -c %y 20120322222.log
2012-01-01 00:00:00.000000000 +0100
So, now we know how to get the age of the file,the question is how to convert that to a three letter month name. The easiest is to use date
:
$ date -d "2012-01-01" +"%b"
Jan
Combining the two commands gives:
$ date -d "$(stat -c %y 20120322222.log)" +"%b"
Jan
So,with this in mind, you can write your script as:
#!/usr/bin/env bash
BASE_DIR=/home/Work/LogFiles
## Find those files that are older than a month
find "$BASE_DIR" -maxdepth 1 -mtime +30 -type f -name "20*" |
while IFS= read -r file; do
## Get the file's modification year
year="$(date -d "$(stat -c %y "$file")" +%Y)"
## Get the file's modification month
month="$(date -d "$(stat -c %y "$file")" +%b)"
## Create the directories if they don't exist. The -p flag
## makes 'mkdir' create the parent directories as needed so
## you don't need to create $year explicitly.
[[ ! -d "$BASE_DIR/$year/$month" ]] && mkdir -p "$BASE_DIR/$year/$month";
## Move the file
mv "$file" "$BASE_DIR/$year/$month"
done
The script above assumes that you want to get real modification date of the files, not parse the name. If you want to parse the name instead let me know and I'll modify accordingly.
Best Answer
Edited not to use ls where a glob would do, as @shawn-j-goff and others suggested.
Just use a
for..do..done
loop:You can replace the
*
with*.txt
or any other glob that returns a list (of files, directories, or anything for that matter), a command that generates a list, e.g.,$(cat filelist.txt)
, or actually replace it with a list.Within the
do
loop, you just refer to the loop variable with the dollar sign prefix (so$f
in the above example). You canecho
it or do anything else to it you want.For example, to rename all the
.xml
files in the current directory to.txt
:Or even better, if you are using Bash you can use Bash parameter expansions rather than spawning a subshell: