Compare commits

...

11 Commits

Author SHA1 Message Date
Emre AKYÜZ
7ea37beb6d
Merge 476b0916c7d89576c6296cd03248fa3eed89bc56 into c43f390f07098c42db5efce654b07870951b512a 2024-10-29 21:54:00 +00:00
appeasementPolitik
c43f390f07
Fix sb-price after bash -> dash change (#1426) 2024-10-22 18:47:41 +00:00
appeasementPolitik
6f67789b8b
Clean up pipewire conf (#1427)
* Clean up pipewire.conf

* Needs extra newline
2024-10-22 18:46:41 +00:00
Rokosun
61026e18de
Fix dangerous copy/move script in lf (#1437)
Context: I accidentally pressed the C key on my .config directory and was presented with a list of directories to copy it to, then I pressed escape to quit the fzf menu without choosing anything - instead of doing nothing the script copied all of the contents inside my .config directory into my home directory. After dealing with that mess I decided to make this PR which does the following:

- Allow users to escape out of the fzf menu without unexpected copies
- Asks the user for confirmation before copying/moving files
- Some improvements in the UI
2024-10-22 18:34:33 +00:00
Emre AKYÜZ
476b0916c7
improve | add info 2024-01-09 01:31:45 +03:00
Emre AKYÜZ
01661e9bba
improve find command 2023-10-20 00:54:21 +03:00
Emre AKYÜZ
a06fe894c9
highly improve and minimize 2023-10-19 23:14:09 +03:00
Emre AKYÜZ
d08eea1cf5
check files with no extensions 2023-07-07 03:42:37 +03:00
Emre AKYÜZ
fe6b9043b8
increased safety 2023-07-07 03:27:50 +03:00
Emre AKYÜZ
62618ae588
increased safety | exclude dotfiles | check root 2023-07-01 04:13:50 +03:00
Emre AKYÜZ
f313b6c0f5
Fix File Naming Conventions for Unix Environment
Luke mentions about Unix naming conventions on his videos. Here is a script to increase consistency according to Unix conventions for all file names in parallel, very easily and fast in a safe way.

Luke also asks: "What do you think about naming files with underscores instead of dashes?", stating his worry about the usage of underscores seems like a "soydev" thing 😂. I give my opinion below. Actually the justification is objective compared to an opinion.

### What The Script Does

**1.** Check if the item is a directory. If so;

- **a)** Remove non-English characters.
- **b)** Replace spaces, dots, and dashes with underscores.
- **c)** Remove consecutive underscores.
- **d)** Convert the name to lowercase.
- **e)** Remove any other special characters.
- **f)** If the resulting name is empty, set it to "untitled".
- **g)** Every file or directory should start and end with an alphanumeric character.

**2.** If the item is a file, apply the same transformations as for directories, but keep the file extension intact.

**3.** Check if the original name and the new name are different. If so, and if a file or directory with the new name already exists, create a unique name.

- The script can use Dash and parallel processes, ensuring safety and performance with a subshell environment. Therefore it can even rename more than 100.000 files that have extremely weird names in 30 seconds (I have tested bash built-in functions, tr, awk and sed. None of them was faster than sed for this task, awk was very close but still slower).

**Examples of How Every File Should Look:** this_is_an_example_directory_name  **OR**  this_is_an_example_video_file.mp4

### Why "_" is Preferred Instead of a Space or a Dot or a Dash

In Unix environments, it is generally recommended to replace spaces in filenames with underscores (_), rather than dots (.) or dashes (-). This is because underscores are more commonly used and supported by Unix utilities and programming languages.

Dots (.) are typically used as a separator between a file's name and its extension, so using them to replace spaces can lead to confusion and errors. Dashes (-) are sometimes used in place of spaces, but they can be problematic because they are often used as a command-line option delimiter in Unix, which can lead to unexpected behavior.

- **Readability:** Underscores make file and directory names more readable, as they clearly separate words and components in the name, whereas spaces can be easily overlooked, and dots can be mistaken for file extensions.

- **Compatibility:** Some command line tools and scripts may not handle file names with spaces or dots properly without additional configuration or escaping. Underscores, on the other hand, do not require special handling and are generally better supported across various tools and environments.

- **URL encoding:** When sharing file paths in URLs or web applications, spaces and dots may require URL encoding (e.g., replacing spaces with "%20" and dots with "%2E"), which can make the URLs less readable and more cumbersome to work with

### The Reason Behind Using a Subshell Environment

Subshells are used in the script to isolate the execution environment of each parallel process. This isolation ensures that the processes do not interfere with each other, as they have their own separate environments, including local variables and function definitions. This separation is particularly important when running multiple processes in parallel, as it reduces the risk of race conditions and other synchronization issues.

Using subshells in the script also simplifies the process of launching parallel processes. By executing the process_item function within a subshell, the script can easily leverage the -P flag of xargs to specify the maximum number of parallel processes to run. This results in improved performance and efficiency when processing a large number of files and directories.

### The Benefit of Removing Non-English Characters

- **Compatibility:** Non-English characters can cause compatibility issues with some tools, applications, or systems that are not properly configured to handle them. By removing these characters, you reduce the risk of encountering issues related to character encoding and ensure broader compatibility across different environments.

- **Consistency:** Standardizing file and directory names by removing non-English characters can make it easier to organize, search, and manage your files. It helps maintain a consistent naming convention across your file system, which can be beneficial for both human users and automated processes.

- **Accessibility:** Using only English characters in file and directory names can improve accessibility for users who may not be familiar with non-English characters or languages. This can be particularly important in multi-user or multi-language environments where not all users might be comfortable with non-English characters.

### A Lot More Details
- find . -depth -name '*' -print0: This find command searches for all files and directories recursively in the current directory (.). -depth ensures that the directory tree is traversed depth-first, and -name '*' matches all items. -print0 prints the results separated by a null character (useful for handling filenames with spaces or special characters).

- | xargs -0 -n1 -P10 -I{} sh -c '...': The find command output is piped (|) to xargs. The -0 option tells xargs to expect null-terminated items. -n1 processes one item at a time. -P10 runs 10 parallel processes. -I{} sets the placeholder for input items. sh -c '...' runs a shell script with the given commands for each input item.

- generate_unique_name() { ... }: This is a function that generates a unique name for a file or directory. It takes three arguments: the base name, the extension (if any), and the destination path. It increments a counter and appends it to the base name until a unique name is found, then returns the unique name.

- process_item() { ... }: This is the main function that processes a single file or directory path. It sanitizes the name and renames the item if needed.

- [ "$item_path" = "." ] && return: This line checks if the item path is the current directory (.). If it is, the function returns without doing anything.

- dir_name=$(dirname "$item_path"); base_name=$(basename "$item_path"): These commands extract the directory name and base name from the item path.

- if [ -d "$item_path" ]; then ... else ... fi: This conditional block checks if the item is a directory (-d) and processes it accordingly.

- new_name=$(echo "$base_name" | sed -E "s/[^a-zA-Z0-9 _.-]+//g; s/[ .-]+/_/g; s/_+/_/g; s/^_//; s/_$//; s/(.*)/\L\1/"): This line uses sed to sanitize the base name by removing unwanted characters, replacing spaces and periods with underscores, and converting the name to lowercase. The -E flag enables extended regular expressions.

- [ -z "$new_name" ] && new_name="untitled": If the new name is empty, it is set to "untitled".

- file_ext="${base_name##*.}" base_name_no_ext="${base_name%.*}": For files, this line extracts the file extension and the base name without the extension.

- new_name="${new_base_name_no_ext}.${file_ext}": For files, this line constructs the new file name with the sanitized base name and the original file extension.

- if [ "$base_name" != "$new_name" ]; then ... fi: This conditional block checks if the original name and the new name are different.

- [ -e "${dir_name}/${new_name}" ] && new_name=$(generate_unique_name "${new_name%.*}" "${new_name##*.}" "$dir_name"): If the new name already exists, the generate_unique_name function is called to get a unique name.

- mv "$item_path" "${dir_name}/${new_name}" 2>/dev/null || true: This line moves (renames) the item to the new path with the sanitized name. If an error occurs, it is redirected to /dev/null (ignored) and the script continues executing due to the || true.

- process_item "{}": This line calls the process_item function with the input item path (represented by {}) as the argument.

- ' 2>/dev/null: This part of the script suppresses any error messages by redirecting the standard error output to /dev/null.
2023-05-10 04:13:36 +00:00
5 changed files with 52 additions and 258 deletions

View File

@ -92,25 +92,37 @@ cmd delete ${{
}}
cmd moveto ${{
clear; tput cup $(($(tput lines)/3)); tput bold
set -f
clear; echo "Move to where?"
dest="$(sed -e 's/\s*#.*//' -e '/^$/d' -e 's/^\S*\s*//' ${XDG_CONFIG_HOME:-$HOME/.config}/shell/bm-dirs | fzf | sed 's|~|$HOME|')" &&
dest=$(sed -e 's/\s*#.*//' -e '/^$/d' -e 's/^\S*\s*//' "${XDG_CONFIG_HOME:-$HOME/.config}/shell/bm-dirs" | fzf --prompt 'Move to where? ' | sed 's|~|$HOME|')
[ -z "$dest" ] && exit
destpath=$(eval printf '%s' \"$dest\")
clear; tput cup $(($(tput lines)/3)); tput bold
echo "From:"
echo "$fx" | sed 's/^/ /'
printf "To:\n %s\n\n\tmove?[y/N]" "$destpath"
read -r ans
[ "$ans" != "y" ] && exit
for x in $fx; do
eval mv -iv \"$x\" \"$dest\"
mv -iv "$x" "$destpath"
done &&
notify-send "🚚 File(s) moved." "File(s) moved to $dest."
notify-send "🚚 File(s) moved." "File(s) moved to $destpath."
}}
cmd copyto ${{
clear; tput cup $(($(tput lines)/3)); tput bold
set -f
clear; echo "Copy to where?"
dest="$(sed -e 's/\s*#.*//' -e '/^$/d' -e 's/^\S*\s*//' ${XDG_CONFIG_HOME:-$HOME/.config}/shell/bm-dirs | fzf | sed 's|~|$HOME|')" &&
dest=$(sed -e 's/\s*#.*//' -e '/^$/d' -e 's/^\S*\s*//' "${XDG_CONFIG_HOME:-$HOME/.config}/shell/bm-dirs" | fzf --prompt 'Copy to where? ' | sed 's|~|$HOME|')
[ -z "$dest" ] && exit
destpath=$(eval printf '%s' \"$dest\")
clear; tput cup $(($(tput lines)/3)); tput bold
echo "From:"
echo "$fx" | sed 's/^/ /'
printf "To:\n %s\n\n\tcopy?[y/N]" "$destpath"
read -r ans
[ "$ans" != "y" ] && exit
for x in $fx; do
eval cp -ivr \"$x\" \"$dest\"
cp -ivr "$x" "$destpath"
done &&
notify-send "📋 File(s) copied." "File(s) copies to $dest."
notify-send "📋 File(s) copied." "File(s) copied to $destpath."
}}
cmd setbg "$1"

View File

@ -1,247 +0,0 @@
# Daemon config file for PipeWire version "0.3.40" #
#
# Copy and edit this file in /etc/pipewire for system-wide changes
# or in ~/.config/pipewire for local changes.
context.properties = {
## Configure properties in the system.
#library.name.system = support/libspa-support
#context.data-loop.library.name.system = support/libspa-support
#support.dbus = true
#link.max-buffers = 64
link.max-buffers = 16 # version < 3 clients can't handle more
#mem.warn-mlock = false
#mem.allow-mlock = true
#mem.mlock-all = false
#clock.power-of-two-quantum = true
#log.level = 2
#cpu.zero.denormals = true
core.daemon = true # listening for socket connections
core.name = pipewire-0 # core name and socket name
## Properties for the DSP configuration.
#default.clock.rate = 48000
#default.clock.allowed-rates = [ 48000 ]
#default.clock.quantum = 1024
#default.clock.min-quantum = 32
#default.clock.max-quantum = 8192
#default.video.width = 640
#default.video.height = 480
#default.video.rate.num = 25
#default.video.rate.denom = 1
#
# These overrides are only applied when running in a vm.
vm.overrides = {
default.clock.min-quantum = 1024
}
}
context.spa-libs = {
#<factory-name regex> = <library-name>
#
# Used to find spa factory names. It maps an spa factory name
# regular expression to a library name that should contain
# that factory.
#
audio.convert.* = audioconvert/libspa-audioconvert
api.alsa.* = alsa/libspa-alsa
api.v4l2.* = v4l2/libspa-v4l2
api.libcamera.* = libcamera/libspa-libcamera
api.bluez5.* = bluez5/libspa-bluez5
api.vulkan.* = vulkan/libspa-vulkan
api.jack.* = jack/libspa-jack
support.* = support/libspa-support
#videotestsrc = videotestsrc/libspa-videotestsrc
#audiotestsrc = audiotestsrc/libspa-audiotestsrc
}
context.modules = [
#{ name = <module-name>
# [ args = { <key> = <value> ... } ]
# [ flags = [ [ ifexists ] [ nofail ] ]
#}
#
# Loads a module with the given parameters.
# If ifexists is given, the module is ignored when it is not found.
# If nofail is given, module initialization failures are ignored.
#
# Uses RTKit to boost the data thread priority.
{ name = libpipewire-module-rtkit
args = {
#nice.level = -11
#rt.prio = 88
#rt.time.soft = 2000000
#rt.time.hard = 2000000
}
flags = [ ifexists nofail ]
}
# Set thread priorities without using RTKit.
#{ name = libpipewire-module-rt
# args = {
# nice.level = -11
# rt.prio = 88
# rt.time.soft = 2000000
# rt.time.hard = 2000000
# }
# flags = [ ifexists nofail ]
#}
# The native communication protocol.
{ name = libpipewire-module-protocol-native }
# The profile module. Allows application to access profiler
# and performance data. It provides an interface that is used
# by pw-top and pw-profiler.
{ name = libpipewire-module-profiler }
# Allows applications to create metadata objects. It creates
# a factory for Metadata objects.
{ name = libpipewire-module-metadata }
# Creates a factory for making devices that run in the
# context of the PipeWire server.
{ name = libpipewire-module-spa-device-factory }
# Creates a factory for making nodes that run in the
# context of the PipeWire server.
{ name = libpipewire-module-spa-node-factory }
# Allows creating nodes that run in the context of the
# client. Is used by all clients that want to provide
# data to PipeWire.
{ name = libpipewire-module-client-node }
# Allows creating devices that run in the context of the
# client. Is used by the session manager.
{ name = libpipewire-module-client-device }
# The portal module monitors the PID of the portal process
# and tags connections with the same PID as portal
# connections.
{ name = libpipewire-module-portal
flags = [ ifexists nofail ]
}
# The access module can perform access checks and block
# new clients.
{ name = libpipewire-module-access
args = {
# access.allowed to list an array of paths of allowed
# apps.
#access.allowed = [
# /usr/bin/pipewire-media-session
#]
# An array of rejected paths.
#access.rejected = [ ]
# An array of paths with restricted access.
#access.restricted = [ ]
# Anything not in the above lists gets assigned the
# access.force permission.
#access.force = flatpak
}
}
# Makes a factory for wrapping nodes in an adapter with a
# converter and resampler.
{ name = libpipewire-module-adapter }
# Makes a factory for creating links between ports.
{ name = libpipewire-module-link-factory }
# Provides factories to make session manager objects.
{ name = libpipewire-module-session-manager }
]
context.objects = [
#{ factory = <factory-name>
# [ args = { <key> = <value> ... } ]
# [ flags = [ [ nofail ] ]
#}
#
# Creates an object from a PipeWire factory with the given parameters.
# If nofail is given, errors are ignored (and no object is created).
#
#{ factory = spa-node-factory args = { factory.name = videotestsrc node.name = videotestsrc Spa:Pod:Object:Param:Props:patternType = 1 } }
#{ factory = spa-device-factory args = { factory.name = api.jack.device foo=bar } flags = [ nofail ] }
#{ factory = spa-device-factory args = { factory.name = api.alsa.enum.udev } }
#{ factory = spa-node-factory args = { factory.name = api.alsa.seq.bridge node.name = Internal-MIDI-Bridge } }
#{ factory = adapter args = { factory.name = audiotestsrc node.name = my-test } }
#{ factory = spa-node-factory args = { factory.name = api.vulkan.compute.source node.name = my-compute-source } }
# A default dummy driver. This handles nodes marked with the "node.always-driver"
# property when no other driver is currently active. JACK clients need this.
{ factory = spa-node-factory
args = {
factory.name = support.node.driver
node.name = Dummy-Driver
node.group = pipewire.dummy
priority.driver = 20000
}
}
{ factory = spa-node-factory
args = {
factory.name = support.node.driver
node.name = Freewheel-Driver
priority.driver = 19000
node.group = pipewire.freewheel
node.freewheel = true
}
}
# This creates a new Source node. It will have input ports
# that you can link, to provide audio for this source.
#{ factory = adapter
# args = {
# factory.name = support.null-audio-sink
# node.name = "my-mic"
# node.description = "Microphone"
# media.class = "Audio/Source/Virtual"
# audio.position = "FL,FR"
# }
#}
# This creates a single PCM source device for the given
# alsa device path hw:0. You can change source to sink
# to make a sink in the same way.
#{ factory = adapter
# args = {
# factory.name = api.alsa.pcm.source
# node.name = "alsa-source"
# node.description = "PCM Source"
# media.class = "Audio/Source"
# api.alsa.path = "hw:0"
# api.alsa.period-size = 1024
# api.alsa.headroom = 0
# api.alsa.disable-mmap = false
# api.alsa.disable-batch = false
# audio.format = "S16LE"
# audio.rate = 48000
# audio.channels = 2
# audio.position = "FL,FR"
# }
#}
]
context.exec = [
#{ path = <program-name> [ args = "<arguments>" ] }
#
# Execute the given program with arguments.
#
# You can optionally start the session manager here,
# but it is better to start it as a systemd service.
# Run the session manager with -h for options.
#
{ path = "/usr/bin/wireplumber" args = "" }
#
# You can optionally start the pulseaudio-server here as well
# but it is better to start it as a systemd service.
# It can be interesting to start another daemon here that listens
# on another address with the -a option (eg. -a tcp:4713).
#
{ path = "/usr/bin/pipewire" args = "-c pipewire-pulse.conf" }
]

View File

@ -0,0 +1,4 @@
context.exec = [
{ path = "/usr/bin/wireplumber" args = "" condition = [ { exec.session-manager = null } { exec.session-manager = true } ] }
{ path = "/usr/bin/pipewire" args = "-c pipewire-pulse.conf" condition = [ { exec.pipewire-pulse = null } { exec.pipewire-pulse = true } ] }
]

23
.local/bin/fixnames Normal file
View File

@ -0,0 +1,23 @@
#!/bin/dash
[ -z "${1}" ] && {
printf "%s\n" "Specify a file path as an argument. e.g., fixnames <path>" >&2
exit "1"
}
[ "$(id -u)" = "0" ] && printf "%s\n" "This script should not be run as root" >&2 && exit "1"
find "${1}" -depth \( -path '*/.*' -o -path '*/.*/*' -o -path '.' \) -prune -o \( -type f -o -type d \) -print0 | sort -zr | xargs -0 -P "0" -I {} dash -c '
base="${1##*/}"
path="${1%/*}"
pattern="s/[^a-zA-Z0-9 ._-]//g; s/[ .-]/_/g; s/_+/_/g; s/^_+//; s/_+$//; s/[A-Z]/\L&/g"
[ -f "${1}" ] && pattern="${pattern}; s/_([^_]+)$/.\\1/"
new_name="$(printf "%s\n" "${base}" | sed -E "${pattern}")"
[ "${base}" != "${new_name}" ] && [ -e "${path}/${new_name}" ] && new_name="${$}_${new_name}"
[ "${base}" != "${new_name}" ] && mv "${1}" "${path}/${new_name}"
' _ {}

View File

@ -28,7 +28,9 @@ filestat="$(stat -c %x "$pricefile" 2>/dev/null)"
[ -d "$dir" ] || mkdir -p "$dir"
updateprice() { curl -sf -m 1 --fail-early $denom.$url/{1$target,$target$interval} --output "$pricefile" --output "$chartfile" ||
updateprice() { curl -sf \
--fail-early "${denom}.${url}/1${target}" "${denom}.${url}/${target}${interval}" \
--output "$pricefile" --output "$chartfile" ||
rm -f "$pricefile" "$chartfile" ;}
[ "${filestat%% *}" != "$(date '+%Y-%m-%d')" ] &&