Bash - Adapting script to rename files with numbers - bash

I have this script
rename_files() {
title="${1##*${2} - }"
for filename in "$1/"*.*; do
case "${filename##*.}" in
ext1|ext2|ext3)
mkdir "/User/Downloaded/${title}"
new_path="/User/Downloaded/${title}/${title}.${filename##*.}"
echo "moving $filename -> $new_path"
mv "$filename" "$new_path"
;;
esac
done
}
rename_category() {
for path in "/User/Downloads/${1}"*; do
rename_files "$path" "$1"
done
}
rename_category CAT1
rename_category CAT2
That do this
Before
.
├── Downloads
│ ├── CAT1 - Something ── File.ext1
│ └── CAT2 - SomethingElse ── OtherFile.ext1
├── Downloaded
├── CAT1
├── CAT2
After
.
├── Downloads
│ ├── CAT1 - Something
│ └── CAT2 - SomethingElse
├── Downloaded
├── CAT1 ── Something ── Something.ext1
├── CAT2 ── SomethingElse ── SomethingElse.ext1
What I'm trying to do is that if only there's more that one file with the same extension, then these files will be renamed adding _1, etc.
Before
.
├── Downloads
│ ├── CAT1 - Something ├── File.ext1
├── ExampleFile.ext1
│ └── CAT2 - SomethingElse ── OtherFile.ext1
├── Downloaded
├── CAT1
├── CAT2
After
.
├── Downloads
│ ├── CAT1 - Something
│ └── CAT2 - SomethingElse
├── Downloaded
├── CAT1 ── Something ── Something_1.ext1
── Something_2.ext1
├── CAT2 ── SomethingElse ── SomethingElse.ext1
EDIT:
#!/bin/bash
rename_files() {
title="${1##*${2} - }"
for filename in "$1/"*.*; do
case "${filename##*.}" in
doc|ext|ext)
mkdir "/User/Downloaded/${title}"
new_path="/User/Downloaded/${title}/${title}.${filename##*.}"
let "iters=1"
while [ -f $new_path ] ; do
$new_path=$new_path"$iters"
let "iters++"
done
echo "moving $filename -> $new_path"
mv "$filename" "$new_path"
;;
esac
done
}
rename_category() {
for path in "/User/Downloads/${1}"*; do
rename_files "$path" "$1"
done
}
rename_category CAT1
EDIT2:
There are two .doc files in /User/Downloads/DOC - TEST
/User/Downloads/DOC - TEST/Sample-doc-file-100kb.doc
/Sample-doc-file-200kb.doc
What I want is
/User/Downloaded/TEST/TEST_1.doc
/TEST_2.doc
This is the output log
chmod +x /User/TEST.sh
sh /User/TEST.sh
moving /User/Downloads/DOC - TEST/Sample-doc-file-100kb.doc -> /User/Downloaded/TEST/TEST.doc
mkdir: /User/Downloaded/TEST: File exists
/User/TEST.sh: line 12: /User/Downloaded/TEST/TEST.doc=/User/Downloaded/TEST/TEST.doc1: No such file or directory
/User/TEST.sh: line 12: /User/Downloaded/TEST/TEST.doc=/User/Downloaded/TEST/TEST.doc2: No such file or directory
etc.
Updated output log
sh /User/Script.sh
moving /User/Downloads/DOC - TEST/Sample-doc-file-100kb.doc -> /User/Downloaded/TEST/TEST.doc
mv: rename {/User/Downloads/DOC - TEST/Sample-doc-file-100kb.doc} to {/User/Downloaded/TEST/TEST.doc}: No such file or directory
mkdir: /User/Downloaded/TEST: File exists
moving /User/Downloads/DOC - TEST/Sample-doc-file-200kb.doc -> /User/Downloaded/TEST/TEST.doc
mv: rename {/User/Downloads/DOC - TEST/Sample-doc-file-200kb.doc} to {/User/Downloaded/TEST/TEST.doc}: No such file or directory
OUTPUT UPDATED:
Here is my initial situation
User/Downloads/DOC - TEST/SampleDoc.doc
/OtherSampleDoc.doc
/OtherDoc.doc
User/Downloaded/
After the script I only obtain
User/Downloads/DOC - TEST/OtherSampleDoc.doc
/OtherDoc.doc
User/Downloaded/TEST/TEST.doc
But want I want would be
User/Downloads/DOC - TEST
User/Downloaded/TEST/TEST_1.doc
/TEST_2.doc
/TEST_3.doc
And this is the output
sh /User/Script.sh
moving /User/Downloads/DOC - TEST/OtherDoc.doc -> /User/Downloaded/TEST/TEST.doc
mkdir: /User/Downloaded/TEST: File exists
/User/Script.sh: line 12: /User/Downloaded/TEST/TEST.doc=/User/Downloaded/TEST/TEST.doc1: No such file or directory
/User/Script.sh: line 12: /User/Downloaded/TEST/TEST.doc=/User/Downloaded/TEST/TEST.doc2: No such file or directory
/User/Script.sh: line 12: /User/Downloaded/TEST/TEST.doc=/User/Downloaded/TEST/TEST.doc3: No such file or directory
etc.

rename_files() {
title="${1##*${2} - }"
for filename in "$1/"*.*; do
case "${filename##*.}" in
ext1|ext2|ext3)
mkdir "/User/Downloaded/${title}"
new_path="/User/Downloaded/${title}/${title}.${filename##*.}"
let "iters=1"
while [ -f $new_path ] ; do
new_path=$new_path"$iters"
let "iters++"
done
echo "moving $filename -> $new_path"
mv "${filename}" "${new_path}"
;;
esac
done
}

Related

Multiline substitution to obtain a tree view

I have a bash script that generates the following output from a certain input using sed and `awk:
# ├── CHILDA1
# │ └── CHILDB1
# │ └── CHILDB2
# │ └── CHILDB3
# │ └── CHILDB4
# │ └── CHILDB5
# │ └── CHILDB6
# │ └── CHILDC1
# │ └── CHILDC2
# │ └── CHILDB7
# ├── CHILDA2
# └──────────────
Is there a way to replace the nest connectors, if they are not the last one, in order to obtain something like this?
# ├──┐CHILDA1
# │ ├── CHILDB1
# │ ├── CHILDB2
# │ ├── CHILDB3
# │ ├── CHILDB4
# │ ├── CHILDB5
# │ ├──┐CHILDB6
# │ │ ├── CHILDC1
# │ │ └── CHILDC2
# │ └── CHILDB7
# ├── CHILDA2
# └──────────────
The first output has been obtained with simple single lines substitutions, I guess the second one needs to check for the row above at the same column (character position). I don't know how tree handles this, but the result I would like to obtain is very similar.
Unicode characters obtained from https://en.wikipedia.org/wiki/Box_Drawing
It would be easier to process the file from the bottom up. This can be achieved using tac.
Through #flags, the following tracks the position of children whose parent has not yet been encountered.
tac |
perl -CSD -Mutf8 -pe'
if ( /[└├]/ ) {
my $i = $-[0]; # Position of the match.
substr($_, $i, 1, "├") if $flags[$i];
$flags[$i] = 1;
my $j = $i+3; # Position of its children.
substr($_, $j, 1, "┐") if $flags[$j];
$flags[$j] = 0;
while ( $i-- ) {
substr($_, $i, 1, "│") if $flags[$i];
}
}
' |
tac
Output
# ├── CHILDA1
# │ ├── CHILDB1
# │ ├── CHILDB2
# │ ├── CHILDB3
# │ ├── CHILDB4
# │ ├── CHILDB5
# │ ├──┐CHILDB6
# │ │ ├── CHILDC1
# │ │ └── CHILDC2
# │ └── CHILDB7
# ├── CHILDA2
# └──────────────
All in Perl:
perl -CSD -Mutf8 -e'
my #lines = reverse <>;
for ( #lines ) {
if ( /[└├]/ ) {
my $i = $-[0]; # Position of the match.
substr($_, $i, 1, "├") if $flags[$i];
$flags[$i] = 1;
my $j = $i+3; # Position of its children.
substr($_, $j, 1, "┐") if $flags[$j];
$flags[$j] = 0;
while ( $i-- ) {
substr($_, $i, 1, "│") if $flags[$i];
}
}
}
print reverse #lines;
'

Gradle - how to iterate in fileTree only for certain type of file

in my gradle task I iterate through fileTree and all works good:
myTask {
fileTree("${project.projectDir}/dir").visit { FileVisitDetails details ->
exec {
//do some operations
}
}
}
but now I have different types of files in my directory:
dir
├── sub1
│ ├── file1.json
│ └── file2.js
├── sub2
│ ├── file1.json
│ └── file2.js
└── sub3
├── file1.js
└── file2.json
How to iterate for only certain type of files? Because
"${project.projectDir}/folder/dir/**/*.json"
doesnt work.
Thanks for any advice
You should use the matching method from FileTree. It uses a PatternFilterable as parameter.
Try that :
fileTree("${project.projectDir}/dir").matching {
include "**/*.json"
}.each {
// do some operations
}

Update a recipe that was previously based on master branch but now is released with version

I have a recipe canboat which was previously based on no official release version and was based on the SRCREV on the master branch.
canboat.bb
SUMMARY = "CANBOAT- A small but effective set of command-line utilities to work with CAN networks on BOATs."
SECTION = "base"
LICENSE = "GPLv3"
DEPENDS += "libxslt-native canboat-native"
LIC_FILES_CHKSUM = "file://GPL;md5=05507c6da2404b0e88fe5a152fd12540"
SRC_URI = "git://github.com/canboat/canboat.git;branch=${SRCBRANCH} \
file://0001-Do-not-use-root-user-group-during-install.patch \
file://0001-Define-ANALYZEREXEC.patch \
file://0001-use-php-instead-of-php5.patch \
"
SRCBRANCH = "master"
SRCREV = "93b2ebfb334d7a9750b6947d3a4af9b091be2432"
S = "${WORKDIR}/git"
PREFIX ?= "${root_prefix}"
#PREFIX_class-native = "${prefix}"
EXTRA_OEMAKE_append_class-target = " ANALYZEREXEC=analyzer "
do_compile() {
oe_runmake
}
do_install() {
oe_runmake DESTDIR=${D} PREFIX=${root_prefix} EXEC_PREFIX=${exec_prefix} install
}
RDEPENDS_${PN}_append_class-target = " php-cli perl"
BBCLASSEXTEND = "native nativesdk"
The main repository did a release officially a couple of days ago and I want to update my recipe to point to v.1.0.0.
Workflow
I used devtool add canboat [link-tar-ball]
copied the changes in the original canboat.bb
changed the name of the recipe to canboat_1.0.0.bb since the recipe now has ${PV} for fetching the right version
Updated recipe
only the SRC_URI now pointing to the .tar.gz is and the md5sums have been updated.
SUMMARY = "CANBOAT- A small but effective set of command-line utilities to work with CAN networks on BOATs."
SECTION = "base"
LICENSE = "GPLv3"
DEPENDS += "libxslt-native canboat-native"
LIC_FILES_CHKSUM = "file://GPL;md5=05507c6da2404b0e88fe5a152fd12540"
SRC_URI = "git://github.com/canboat/canboat.git;branch=${SRCBRANCH} \
file://0001-Do-not-use-root-user-group-during-install.patch \
file://0001-Define-ANALYZEREXEC.patch \
file://0001-use-php-instead-of-php5.patch \
"
SRC_URI = "https://github.com/canboat/canboat/archive/v${PV}.tar.gz"
SRC_URI[md5sum] = "6ee6162d30faa3b3f1ff068cc7a70a60"
SRC_URI[sha256sum] = "6bf1050a83a5d7eb8351547c10e7e2ae2e1811250d50a63880074f0c07ec672e"
S = "${WORKDIR}/git"
PREFIX ?= "${root_prefix}"
#PREFIX_class-native = "${prefix}"
EXTRA_OEMAKE_append_class-target = " ANALYZEREXEC=analyzer "
do_compile() {
oe_runmake
}
do_install() {
oe_runmake DESTDIR=${D} PREFIX=${root_prefix} EXEC_PREFIX=${exec_prefix} install
}
RDEPENDS_${PN}_append_class-target = " php-cli perl"
BBCLASSEXTEND = "native nativesdk"
I tried bitbake -k canboat to check the build process
Error
I get a QA error as following:
QA Issue: canboat-native: LIC_FILES_CHKSUM points to an invalid file:
/home/des/Yocto/PHYTEC_BSPs/yocto_fsl/build/tmp/work/x86_64-linux/canboat-native/1.0.0-r0/git/GPL
I tried going into the above mentioned folder and there was no GPL file there on the contrary the file is present in the canboat_1.0.0 folder.
The structure is as follows:
.
├── canboat-1.0.0
│   ├── actisense-serial
│   ├── airmar
│   ├── analyzer
│   ├── candump2analyzer
│   ├── common
│   ├── config
│   ├── group-function
│   ├── ip
│   ├── n2kd
│   ├── nmea0183
│   ├── samples
│   ├── send-message
│   ├── socketcan-writer
│   └── util
├── git
└── temp
and the git folder has nothing in it.
Question
How do I overcome the QA test and is there a better way to update the recipes?
You don't need S = "${WORKDIR}/git" in your new recipe. When you refer specific version from tarball, yocto de-references the path using ${PN}-${PV}
This is because when tarball is extracted, the source path will be ${WORKDIR}/${PN}-${PV}.
Additionally, you can remove do_compile section of your recipe as Yocto by default calls make when it can't find Makefile.am/in or autoconf files.

Make symlinks for all files in directory (recursively) into other directory

I have files in folder:
folder_a/
subfolder_1/
file.txt
subfolder_2/
subfolder_3
file2.txt
file3.txt
I need to get symlinks to .txt-files into folder_b:
folder_b/
000_file.txt ---> folder_a/subfolder_1/file.txt
001_file2.txt ---> folder_a/subfolder_2/subfolder_3/file2.txt
003_file3.txt ---> folder_a/file3.txt
In Bash:
shopt -s globstar # Enable **/* glob
for fname in folder_a/**/*.txt; do # Get all .txt in folder_a
bname=${fname##*/} # Basename of link target
# Assemble link name
printf -v lname '%s%03d%s' 'folder_b/' "${bname//[!0-9]}" "_$bname"
# Create link
ln -s "$fname" "$lname"
done
resulting in
.
├── folder_a
│   ├── file3.txt
│   ├── subfolder_1
│   │   └── file.txt
│   └── subfolder_2
│   └── subfolder_3
│   └── file2.txt
└── folder_b
├── 000_file.txt -> folder_a/subfolder_1/file.txt
├── 002_file2.txt -> folder_a/subfolder_2/subfolder_3/file2.txt
└── 003_file3.txt -> folder_a/file3.txt
Can do this with ruby script:
src = '/path/to/folder_a/'
dst = '/path/to/folder_b/'
files = `find $(realpath #{src}) -type f -iname "*.txt"`.split("\n")
files.each_with_index do |path, idx|
name = File.basename path
`ln -s "#{path}" "#{dst + "%03d" % idx}__#{name}"`
end

Why Dir.glob in Ruby doesn't see files in folders named with square brackets?

I have this tree :
.
├── folders
│   ├── foo
│   │   └── fuu.flac
│   ├── foo [bar]
│   │   └── fuu.flac
│   └── foo[bar]
│   └── fuu.flac
└── test.rb
and this code :
#!/bin/env ruby
## encoding: utf-8
Dir.glob('./folders/*').each do |path|
puts "Contents of #{path} :"
Dir.glob(File.join(path, '*')).each do |file_path|
puts "\t #{file_path}"
end
end
I expect to see my three fuu.flac files. However the script doesn't show the files in the folders with square brackets in the name.
Here is the output :
Contents of ./folders/foo [bar] :
Contents of ./folders/foo[bar] :
Contents of ./folders/foo :
./folders/foo/fuu.flac
Is this a normal beahvior of Ruby, or did I miss something ?
(I am using Ruby 1.9.3 under Ubuntu 12.10)
The square brackets have a special meaning in the context of shell globbing. foo[bar] matches foob, fooa or foor, but obviously not foo[bar]. If you really want to dynamically generate such a pattern, you will need to at least escape the characters \?{}[]. using a backslash:
def escape_glob(s)
s.gsub(/[\\\{\}\[\]\*\?]/) { |x| "\\"+x }
end
# ...
Dir.glob("#{escape_glob(path)}/*").each do |file_path|
# ...
end

Resources