I have about 100 directories all in the same parent directory that adhere to the naming convention [sitename].com. I want to rename them all [sitename].subdomain.com.
Here's what I tried:
for FILE in `ls | sed 's/.com//' | xargs`;mv $FILE.com $FILE.subdomain.com;
But it fails miserably. Any ideas?
Use rename(1).
rename .com .subdomain.com *.com
And if you have a perl rename instead of the normal one, this works:
rename s/\\.com$/.subdomain.com/ *.com
Using bash:
for i in *
do
mv $i ${i%%.com}.subdomain.com
done
The ${i%%.com} construct returns the value of i without the '.com' suffix.
What about:
ls |
grep -Fv '.subdomain.com' |
while read FILE; do
f=`basename "$FILE" .com`
mv $f.com $f.subdomain.com
done
See: http://blog.ivandemarino.me/2010/09/30/Rename-Subdirectories-in-a-Tree-the-Bash-way
#!/bin/bash
# Simple Bash script to recursively rename Subdirectories in a Tree.
# Author: Ivan De Marino <ivan.demarino#betfair.com>
#
# Usage:
# rename_subdirs.sh <starting directory> <new dir name> <old dir name>
usage () {
echo "Simple Bash script to recursively rename Subdirectories in a Tree."
echo "Author: Ivan De Marino <ivan.demarino#betfair.com>"
echo
echo "Usage:"
echo " rename_subdirs.sh <starting directory> <old dir name> <new dir name>"
exit 1
}
[ "$#" -eq 3 ] || usage
recursive()
{
cd "$1"
for dir in *
do
if [ -d "$dir" ]; then
echo "Directory found: '$dir'"
( recursive "$dir" "$2" "$3" )
if [ "$dir" == "$2" ]; then
echo "Renaming '$2' in '$3'"
mv "$2" "$3"
fi;
fi;
done
}
recursive "$1" "$2" "$3"
find . -name '*.com' -type d -maxdepth 1 \
| while read site; do
mv "${site}" "${site%.com}.subdomain.com"
done
Try this:
for FILE in `ls -d *.com`; do
FNAME=`echo $FILE | sed 's/\.com//'`;
`mv $FILE $FNAME.subdomain.com`;
done
Related
I have to extract all archives in my current folder. What I'm doing only extracts all that are named correctly but the archives can have any messed up extension on them.
file.tar.gvz
or file.tar.potatogz
or file.sss.faz
gunzip *.tar.gz >/dev/null 2>/dev/null
echo $?
echo "gzip"
tar -xvf *.tar >/dev/null 2>/dev/null
echo $?
echo "tar"
unzip '*.zip' >/dev/null 2>/dev/null
echo $?
echo "zip"
Edit:
The file command seems like the right way to go but I can't get it to work in a nested loop. when outside the directory loop it works fine.
for D in *; do
if [ -d "${D}" ]; then
cd $D
bool=false
for files in *
do
type=$( file -b $files | awk '{printf $1;}' )
echo "next is type"
echo $type
done
cd..
done
The File command solved this.
My problems with file were solved with quotation marks.
type=$( file -b "$j" | awk '{printf $1;}' )
When gunzip reads from stdin, it doesn't know that the filename was wrong:
cat archive_with_wrong_name | gunzip -c
Or even easier...
gunzip -c <archive_with_wrong_name
Or even easier...
gzcat archive_with_wrong_name
Looks like you are real close. How about something like this?
for D in *; do
if [ -d "${D}" ]; then
cd $D
for file in *; do
type="$( file -b "$file" | awk '{print $1}' )"
case "$type" in
'gzip' ) gunzip $file; continue ;;
'zip' ) unzip $file; continue ;;
'tar' ) tar xzf $file; continue ;;
'*' ) continue ;;
esac
done
cd ..
fi
done
I have searched many forums and websites to create an ALAC collection from my FLAC collection with the same directory structure with no success. Therefore I coded my own shell script and decided to share here so others can use or improve on it.
Problems I wanted to solve:
Full automation of conversion. I did not want to go and run scripts
in each and every directory.
Recursive file search
Moving all the structure from one location to another by converting flac to alac and copying the artwork. nothing else.
I did not want flac and alac files in the same directory.(which the below
script I believe can do that)
Here is how the script turned out. It works for me, I hope it does for you as well. I am using Linux Mint and bash shell.
2014-12-08 - Made some changes and now it is working fine. Before it was creating multiple copies.
Usage is: ./FLACtoALAC.sh /sourcedirectory /targetdirectory
Here are some explanations:
Source: /a/b/c/d/e/ <- e has flac
/g/f/k <- k has artwork
/l <- l has mp3
Target: /z/u/v/g/f
when the command is run : ./FLACtoALAC.sh /a/b/ /z/u/
I want the structure look like:
/z/u/v/g/f <- f was already there
/c/d/e/ <- e had flac, so created with the tree following source (/a/b)
/c/g/f/k <- k had artwork, so created with the tree following source (/a/b)
not created l <- l did not have any of the png,jpg or flac files.
I do not want to create any directory that does not contain png, jpg or flac,
unless it is a parent to one of such those directories.
Now the updated code:
#!/bin/bash
if [[ $1 ]]
then
if [[ ${1:0:1} = / || ${1:0:1} = ~ ]]
then Source_Dir=$1
elif [[ ${1:0:1} = . ]]
then Source_Dir=`pwd`
else Source_Dir=`pwd`'/'$1
fi
else Source_Dir=`pwd`'/'
fi
if [[ $2 ]]
then
if [[ ${2:0:1} = / || ${2:0:1} = ~ ]]
then Target_Dir=$2
elif [[ ${2:0:1} = . ]]
then Target_Dir=`pwd`
else Target_Dir=`pwd`'/'$2
fi
else Target_Dir=`pwd`'/'
fi
echo "Source Directory : "$Source_Dir
echo "Target Directory : "$Target_Dir
typeset -i Source_Dir_Depth
Source_Dir_Depth=`echo $Source_Dir | grep -oi "\/" | wc -l`
typeset -i Target_Dir_Depth
Target_Dir_Depth=`echo $Target_Dir | grep -oi "\/" | wc -l`
echo "Depth of the Source Directory: "$Source_Dir_Depth
echo "Depth of the Target Directory: "$Target_Dir_Depth
echo "Let's check if the Target Directory exists, if not we will create"
typeset -i Number_of_depth_checks
Number_of_depth_checks=$Target_Dir_Depth+1
for depth in `seq 2 $Number_of_depth_checks`
do
Target_Directory_Tree=`echo ${Target_Dir} | cut -d'/' -f-${depth}`
if [[ -d "$Target_Directory_Tree" ]]
then
echo "This directory exists ("$Target_Directory_Tree"), moving on"
else
Create_Directory=`echo ${Target_Dir} | cut -d'/' -f-${depth}`
echo "Creating the directory/subdirectory $Create_Directory"
mkdir -pv "$Create_Directory"
fi
done
Directory_List=`find "${Source_Dir}" -type d -exec sh -c 'ls -tr -1 "{}" | sort | egrep -iq "*.(jpg|png|flac)$"' ';' -print`
oIFS=$IFS
IFS=$'\n'
for directories in $Directory_List
do
echo "Directories coming from the source : $directories"
typeset -i directories_depth
directories_depth=`echo $directories | grep -oi "\/" | wc -l`
echo "Number of sub-directories to be checked: $Source_Dir_Depth"
typeset -i number_of_directories_depth
number_of_directories_depth=$directories_depth+1
for depth in `seq 2 $number_of_directories_depth`
do
Source_Tree=`echo ${Source_Dir} | cut -d'/' -f-${depth}`
Subdirectory_Tree=`echo ${directories} | cut -d'/' -f-${depth}`
Subdirectory_Remaining_Tree=`echo ${directories} | cut -d'/' -f${depth}-`
echo "source tree : $Source_Tree"
echo "source tree : $Subdirectory_Tree"
if [[ $depth -le $Source_Dir_Depth && $Source_Tree = $Subdirectory_Tree ]]
then
echo "Common Directory, skipping ($Subdirectory_Tree)"
continue
else
export Targetecho=$(echo $Target_Dir | sed -e 's/\r//g')
export Destination_Directory=${Targetecho}${Subdirectory_Remaining_Tree}
echo "Destination directory is : $Destination_Directory"
export Sub_directories_depth=`echo $Destination_Directory | grep -oi "\/" | wc -l`
echo "Total destination depth : $Sub_directories_depth"
echo "Now we are checking target directory structure"
fi
break
done
echo "Gettin into the new loop to verify/create target structure"
typeset -i number_of_Sub_directories_depth
number_of_Sub_directories_depth=$Sub_directories_depth+1
for subdepth in `seq 2 $number_of_Sub_directories_depth`
do
Target_Subdirectory_Tree=`echo ${Destination_Directory} | cut -d'/' -f-${subdepth}`
if [[ $subdepth < $number_of_Sub_directories_depth && -d "$Target_Subdirectory_Tree" ]]
then
echo "Directory already exists in the destination ($Target_Subdirectory_Tree)"
elif [[ $subdepth < $number_of_Sub_directories_depth && ! -d "$Target_Subdirectory_Tree" ]]
then
echo "Creating the path in the destination ($Target_Subdirectory_Tree)"
mkdir -pv "$Target_Subdirectory_Tree"
elif [[ $subdepth -eq $number_of_Sub_directories_depth ]]
then
if [[ ! -d "$Destination_Directory" ]]
then
echo "Creating Directory: $Destination_Directory"
mkdir -pv "$Destination_Directory"
fi
echo "Directory already exists in the destination ($Destination_Directory)"
#Flac file processing starts here once the directory is found
Flac_File_List=`(shopt -s nocaseglob ; ls -tr "${directories}"/*.flac | sort)`
echo "List of files in $directories :"
echo $Flac_File_List
for flac_files in $Flac_File_List
do
echo "files : $flac_files"
typeset -i flac_file_depth
flac_file_depth=`echo $flac_files | grep -oi "\/" | wc -l`
flac_file_depth=$flac_file_depth+1
echo "flac_file_depth : $flac_file_depth"
Flac_File_Name=`echo ${flac_files} | cut -d'/' -f${flac_file_depth}`
echo "Flac_File Name : $Flac_File_Name"
Destination_File=${Destination_Directory}'/'${Flac_File_Name}
echo "will convert $Flac_File_Name from $flac_files to $Destination_File"
yes | ffmpeg -i "$flac_files" -vf "crop=((in_w/2)*2):((in_h/2)*2)" -c:a alac "${Destination_File%.flac}.m4a"
done
#Artwork file processing starts here once the directory is found
Art_File_List=`(shopt -s nocaseglob ; ls -tr "${directories}"/*.{png,jpg} | sort)`
echo "List of files in $directories :"
echo $Art_File_List
for art_files in $Art_File_List
do
echo "files : $art_files"
typeset -i art_file_depth
art_file_depth=`echo $art_files | grep -oi "\/" | wc -l`
art_file_depth=$art_file_depth+1
echo "file_depth : $art_file_depth"
Art_File_Name=`echo ${art_files} | cut -d'/' -f${art_file_depth}`
echo "File Name : $Art_File_Name"
Destination_File=${Destination_Directory}'/'${Art_File_Name}
echo "will copy $Art_File_Name from $art_files to $Destination_File"
cp "$art_files" "$Destination_File"
done
else
echo "did nothing!!!"
fi
done
done
IFS=$oIFS
feel free to change, improve, distribute.
Caglar
Try this out:
#!/bin/bash
src_dir="in"
dst_dir="out"
find ${src_dir} -type f -print0|while IFS= read -r -d '' src_file; do
dst_file=${src_file/$src_dir/$dst_dir}
echo "src_file=${src_file} dst_file=${dst_file}"
mkdir -pv `dirname $dst_file`
# use above variables and run convert command with it here
done
To test how it works:
mkdir in out
cd in
mkdir 1 2 3
find . -type d -exec touch {}/foo {}/bar {}/baz \;
cd ..
./run_my_script.sh
Now you only need to attach your convert function/script/command/whatever and improve it to read src_dir and dst_dir from the command line (I would recommend man bash - > getopts)
I have no idea I have spent a lot of hours dealing with this problem. I need to write script. Script should loop recursively through subdirectories in current directory. It should check files count in each directory. If file count is greater than 10 it should write all names of these file in file named "BigList" otherwise it should write in file "ShortList". This should look like
---<directory name>
<filename>
<filename>
<filename>
<filename>
....
---<directory name>
<filename>
<filename>
<filename>
<filename>
....
My script only works if subdirecotries don't include subdirectories in turn.
I am confused about this. Because it doesn't work as I expect. It will take less than 5 minutes to write this on any programming language for my.
Please help to solve this problem , because I have no idea how to do this.
Here is my script
#!/bin/bash
parent_dir=""
if [ -d "$1" ]; then
path=$1;
else
path=$(pwd)
fi
parent_dir=$path
loop_folder_recurse() {
local files_list=""
local cnt=0
for i in "$1"/*;do
if [ -d "$i" ];then
echo "dir: $i"
parent_dir=$i
echo before recursion
loop_folder_recurse "$i"
echo after recursion
if [ $cnt -ge 10 ]; then
echo -e "---"$parent_dir >> BigList
echo -e $file_list >> BigList
else
echo -e "---"$parent_dir >> ShortList
echo -e $file_list >> ShortList
fi
elif [ -f "$i" ]; then
echo file $i
if [ $cur_fol != $main_pwd ]; then
file_list+=$i'\n'
cnt=$((cnt + 1))
fi
fi
done
}
echo "Base path: $path"
loop_folder_recurse $path
I believe that this does what you want:
find . -type d -exec env d={} bash -c 'out=Shortlist; [ $(ls "$d" | wc -l) -ge 10 ] && out=Biglist; { echo "--$d"; ls "$d"; echo; } >>"$out"' ';'
If we don't want either to count subdirectories to the cut-off or to list them in the output, then use this version:
find . -type d -exec env d={} bash -c 'out=Shortlist; [ $(ls -p "$d" | grep -v "/$" | wc -l) -ge 10 ] && out=Biglist; { echo "--$d"; ls -p "$d"; echo; } | grep -v "/$" >>"$out"' ';'
My assignment is to write a Unix shell script that asks the user for the name of a directory, and then works exactly like find.
Here is what I have so far:
#!/bin/bash
dir_lister()
{
cd "$1"
echo "$1"
list=$(ls -l ${1})
nolines=$(echo "$list" | awk 'END{printf "%d",NF}')
if [ $nolines -eq 2 ]
then
echo "$1"
return
fi
filelist=$(echo "$list" | grep ^-.*)
dirlist=$(echo "$list" | grep ^d.*)
filename=$(echo "$filelist"| awk '{printf "%s\n",$NF}')
present=$(pwd)
echo "$filename"| awk -v pres=$present '{printf "%s/%s\n",pres,$0}'
dirlist2=$(echo "$dirlist" | awk '{printf "%s\n",$NF}')
echo "$dirlist2" | while IFS= read -r line;
do
nextCall=$(echo "$present/$line");
dir_lister $nextCall;
cd ".."
done
cd ".."
}
read -p "Enter the name of the direcotry: " dName
dir_lister $dName
The problem is, after a depth of three directories, this script gets into an infinite loop, and I don't see why.
EDIT:
Here is the code i came up with after looking at your answer, it still doesn't go more than 1 directory depth:
#!/bin/bash
shopt -s dotglob # don't miss "hidden files"
shopt -s nullglob # don't fail on empty directories
list_directory()
{
cd "$2"
cd "$1"
##echo -e "I am called \t $1 \t $2"
for fileName in "$1/"*
do
##echo -e "hello \t $fileName"
if [ -d "$fileName" ];
then
echo "$fileName"
list_directory $fileName $2
else
echo "$fileName"
fi
done
}
read -p "Enter the direcotory Name: " dirName
var=$(pwd)
list_directory $dirName $var
Okay, that is completely the wrong way to list files in a directory (see ParsingLs). I'll give you the pieces and you should be able to put them together into a working script.
Put this at the top of your script:
shopt -s dotglob # don't miss "hidden files"
shopt -s nullglob # don't fail on empty directories
Then you can easily loop over directory contents with:
for file in "$directory/"* ; do
#...
done
Test if you have a directory:
if [ -d "$file" ] ; then
# "$file" is a directory, recurse...
fi
I got this
for file in *; do
any command
done
What I want to do is add an exception to the "for file in *; do".
Any ideas?
If you wanted to skip files with a particular extension, for example, ".pl", you could do:
for file in *
do
[ "${file##*.}" != "pl" ] && echo $file
done
One way to do what I think you are asking is to loop through and check a file name with a if statement (or just grep -v the ls cmd):
for file in `ls`; do
if [ "$file" == "something" ]; then
# do something
else
# something else
fi
done
For example, you have files
$ ls -1 ./
./M2U0001.MPG
./M2U0180.MPG
./text
Exception file is M2U0180.MPG
$> filename="M2U0180.MPG"
And
$> for file in $(ls -1 ./* | grep --invert-match "${filename}" ); do echo $file; done
./M2U0001.MPG
./text
Weird solution done :)
use bash's extended globbing
shopt -s extglob
for f in !(excluded-file); do echo "$f"; done
A simple solution :
The following code snippet will print all the files in the pwd , that have a .py extension
for i in * ;do
if [[ $i == *.py ]];then
echo "$i"
fi
done