Full Code of HariSekhon/DevOps-Bash-tools for AI

master 318dd0e61bd4 cached
1804 files
4.8 MB
1.3M tokens
1 requests
Download .txt
Showing preview only (5,351K chars total). Download the full file or copy to clipboard to get everything.
Repository: HariSekhon/DevOps-Bash-tools
Branch: master
Commit: 318dd0e61bd4
Files: 1804
Total size: 4.8 MB

Directory structure:
gitextract_vlrxn056/

├── .appveyor.yml
├── .bash.d/
│   ├── Makefile
│   ├── README.md
│   ├── aliases.sh
│   ├── android.sh
│   ├── ansible.sh
│   ├── argocd.sh
│   ├── aws-cloudshell.sh
│   ├── aws.sh
│   ├── azure.sh
│   ├── bash_it.sh
│   ├── circleci.sh
│   ├── colors.sh
│   ├── custom.sh
│   ├── direnv.sh
│   ├── docker.sh
│   ├── env.sh
│   ├── functions.sh
│   ├── gcp.sh
│   ├── git.sh
│   ├── golang.sh
│   ├── gpg-agent.sh
│   ├── grype.sh
│   ├── hadoop.sh
│   ├── intellij.sh
│   ├── java.sh
│   ├── jenkins.sh
│   ├── k3d.sh
│   ├── kafka.sh
│   ├── kubernetes.sh
│   ├── linux.sh
│   ├── lolcat.sh
│   ├── mac.sh
│   ├── mercurial.sh
│   ├── mp3.sh
│   ├── mysql.sh
│   ├── network.sh
│   ├── nodejs.sh
│   ├── os_detection.sh
│   ├── paths.sh
│   ├── perl.sh
│   ├── postgres.sh
│   ├── prompt.sh
│   ├── python.sh
│   ├── rancid.sh
│   ├── ruby.sh
│   ├── screen.sh
│   ├── skaffold.sh
│   ├── spinner.sh
│   ├── spotify.sh
│   ├── ssh-agent.sh
│   ├── ssh.sh
│   ├── svn.sh
│   ├── teamcity.sh
│   ├── terraform.sh
│   ├── title.sh
│   ├── travis_ci.sh
│   ├── trivy.sh
│   ├── vagrant.sh
│   ├── vim.sh
│   ├── virtualbox.sh
│   ├── vnc.sh
│   ├── welcome.sh
│   ├── when.sh
│   └── z_final.sh
├── .bash_logout
├── .bash_profile
├── .bashrc
├── .buildkite/
│   └── pipeline.yml
├── .circleci/
│   └── config.yml
├── .cirrus.yml
├── .dockerignore
├── .drone.yml
├── .editorconfig
├── .envrc
├── .envrc-aws
├── .envrc-gcp
├── .envrc-java
├── .envrc-kubernetes
├── .envrc-python
├── .envrc-terraform
├── .git-templates/
│   └── git-secrets/
│       └── hooks/
│           ├── commit-msg
│           ├── pre-commit
│           └── prepare-commit-msg
├── .gitconfig
├── .gitconfig.local
├── .github/
│   ├── CODEOWNERS
│   ├── ISSUE_TEMPLATE.md
│   └── workflows/
│       ├── actions-allowed.txt
│       ├── alpine.yaml
│       ├── alpine_3.yaml
│       ├── centos.yaml.disabled
│       ├── centos7.yaml.disabled
│       ├── centos8.yaml.disabled
│       ├── checkov.yaml
│       ├── codeowners.yaml
│       ├── commit_adjacent_repos.sh
│       ├── debian.yaml
│       ├── debian_10.yaml
│       ├── debian_11.yaml
│       ├── debian_12.yaml
│       ├── debian_6.yaml.disabled
│       ├── debian_7.yaml.disabled
│       ├── debian_8.yaml.disabled
│       ├── debian_9.yaml.disabled
│       ├── docker_bash_alpine.yaml
│       ├── docker_bash_centos.yaml
│       ├── docker_bash_debian.yaml
│       ├── docker_bash_fedora.yaml
│       ├── docker_bash_ubuntu.yaml
│       ├── dockerhub_status_alpine.yaml.disabled
│       ├── dockerhub_status_centos.yaml.disabled
│       ├── dockerhub_status_debian.yaml.disabled
│       ├── dockerhub_status_fedora.yaml.disabled
│       ├── dockerhub_status_ubuntu.yaml.disabled
│       ├── fedora.yaml
│       ├── fork-sync.yaml
│       ├── fork-update-pr.yaml
│       ├── ghcr_bash_ubuntu.yaml.disabled
│       ├── grype.yaml
│       ├── json.yaml
│       ├── kics.yaml
│       ├── mac.yaml
│       ├── mac_11.yaml
│       ├── mac_12.yaml
│       ├── markdown.yaml
│       ├── push_all_repos.sh
│       ├── pypy2.yaml.disabled
│       ├── pypy3.yaml.disabled
│       ├── python2.7.yaml.disabled
│       ├── python3.10.yaml
│       ├── python3.11.yaml
│       ├── python3.6.yaml.disabled
│       ├── python3.7.yaml
│       ├── python3.8.yaml
│       ├── python3.9.yaml
│       ├── self_hosted.yaml.disabled
│       ├── semgrep-cloud.yaml
│       ├── semgrep.yaml
│       ├── shellcheck.yaml
│       ├── sonarcloud.yaml
│       ├── sync_to_adjacent_repos.sh
│       ├── trivy.yaml
│       ├── trivy_image.yaml
│       ├── ubuntu.yaml
│       ├── ubuntu_14.04.yaml.disabled
│       ├── ubuntu_16.04.yaml.disabled
│       ├── ubuntu_18.04.yaml.disabled
│       ├── ubuntu_20.04.yaml
│       ├── ubuntu_22.04.yaml
│       ├── ubuntu_github.yaml
│       ├── url_links.yaml.disabled
│       ├── validate.yaml
│       ├── xml.yaml
│       └── yaml.yaml
├── .gitignore
├── .gitlab-ci.yml
├── .gitmodules
├── .hound.yml
├── .mdl.rb
├── .mdlrc
├── .pre-commit-config.yaml
├── .pylintrc
├── .scrutinizer.yml
├── .semaphore/
│   └── semaphore.yml
├── .sonarcloud.properties
├── .sonarlint/
│   └── connectedMode.json
├── .terraformignore
├── .trivyignore
├── .zlogin
├── .zlogout
├── .zprofile
├── .zshenv
├── .zshrc
├── DOCKER_STATUS.md
├── Gemfile
├── Jenkinsfile
├── LICENSE
├── Makefile
├── Makefile.in
├── README.md
├── STARCHARTS.md
├── STATUS.md
├── ai/
│   └── openai_api.sh
├── applescript/
│   ├── app_names.sh
│   ├── browser_close_tab.scpt
│   ├── browser_get_default.scpt
│   ├── com.harisekhon.wakeup_script.plist
│   ├── get_application_names.scpt
│   ├── get_frontmost_process.scpt
│   ├── get_frontmost_process_title.scpt
│   ├── get_mouse_coordinates.scpt
│   ├── get_mouse_coordinates.sh
│   ├── is_screen_locked.py
│   ├── is_screensaver_running.scpt
│   ├── keystrokes.sh
│   ├── mouse_clicks.scpt
│   ├── mouse_clicks.sh
│   ├── mouse_clicks_remote_desktop.sh
│   ├── mouse_random_movements.sh
│   ├── reopen_app.sh
│   ├── screensaver_activate.scpt
│   ├── set_frontmost_process.scpt
│   ├── set_mic_internal.sh
│   ├── shazam_app_delete_track.sh
│   ├── shazam_app_dump_tracks.sh
│   ├── shazam_search_spotify.sh
│   ├── shazam_search_spotify_then_delete_track.sh
│   ├── shorten_text_selection.scpt
│   ├── spotify_app_search.sh
│   ├── start_app_at_login.sh
│   ├── wakeup_script.sh
│   └── world_clock_cities.txt
├── appveyor/
│   ├── appveyor_api.sh
│   ├── appveyor_byoc.sh
│   ├── appveyor_byoc_debian.sh
│   └── appveyor_delete_offline_byoc.sh
├── aws/
│   ├── .aws_customize_environment
│   ├── aws_account_summary.sh
│   ├── aws_accounts_missing_from_config.sh
│   ├── aws_batch_kill_stale_jobs.sh
│   ├── aws_batch_stale_jobs.sh
│   ├── aws_billing_alarm.sh
│   ├── aws_budget.json
│   ├── aws_budget_alarm.sh
│   ├── aws_budget_notification.json
│   ├── aws_budget_sns_access_policy.json
│   ├── aws_cli_create_credential.sh
│   ├── aws_cloudformation_stacks_pending.sh
│   ├── aws_cloudfront_distribution_for_origin.sh
│   ├── aws_cloudtrails_cloudwatch.sh
│   ├── aws_cloudtrails_event_selectors.sh
│   ├── aws_cloudtrails_s3_accesslogging.sh
│   ├── aws_cloudtrails_s3_kms.sh
│   ├── aws_cloudtrails_status.sh
│   ├── aws_codecommit_csv_creds.sh
│   ├── aws_config_all_types.sh
│   ├── aws_config_recording.sh
│   ├── aws_csv_creds.sh
│   ├── aws_ec2_ami_boot.sh
│   ├── aws_ec2_ami_boot_ssh.sh
│   ├── aws_ec2_ami_create_from_instance.sh
│   ├── aws_ec2_ami_ids.sh
│   ├── aws_ec2_ami_name_to_id.sh
│   ├── aws_ec2_ami_share_to_account.sh
│   ├── aws_ec2_amis.sh
│   ├── aws_ec2_ebs_create_snapshot_and_wait.sh
│   ├── aws_ec2_ebs_resize_and_wait.sh
│   ├── aws_ec2_ebs_volumes.sh
│   ├── aws_ec2_ebs_volumes_unattached.sh
│   ├── aws_ec2_instance_clone.sh
│   ├── aws_ec2_instance_ip.sh
│   ├── aws_ec2_instance_name_to_id.sh
│   ├── aws_ec2_instance_terminate_by_name.sh
│   ├── aws_ec2_instance_wait_for_ready.sh
│   ├── aws_ec2_instances.sh
│   ├── aws_ec2_launch_templates_ami_id.sh
│   ├── aws_ecr_alternate_tags.sh
│   ├── aws_ecr_delete_old_tags.sh
│   ├── aws_ecr_delete_tag.sh
│   ├── aws_ecr_docker_build_push.sh
│   ├── aws_ecr_docker_login.sh
│   ├── aws_ecr_list_repos.sh
│   ├── aws_ecr_list_tags.sh
│   ├── aws_ecr_newest_image_tags.sh
│   ├── aws_ecr_tag_branch.sh
│   ├── aws_ecr_tag_datetime.sh
│   ├── aws_ecr_tag_image.sh
│   ├── aws_ecr_tag_image_by_digest.sh
│   ├── aws_ecr_tag_latest.sh
│   ├── aws_ecr_tag_newest_as_latest.sh
│   ├── aws_ecr_tags_old.sh
│   ├── aws_ecr_tags_timestamps.sh
│   ├── aws_eks_addon_versions.sh
│   ├── aws_eks_ami_create.sh
│   ├── aws_eks_available_ips.sh
│   ├── aws_eks_cloudwatch_logs.sh
│   ├── aws_eks_cluster_versions.sh
│   ├── aws_eks_ssh_dump_logs.sh
│   ├── aws_elasticache_serverless_list.sh
│   ├── aws_emr_clusters_last_steps.sh
│   ├── aws_foreach_profile.sh
│   ├── aws_foreach_region.sh
│   ├── aws_iam_generate_credentials_report_wait.sh
│   ├── aws_iam_harden_password_policy.sh
│   ├── aws_iam_password_policy.sh
│   ├── aws_iam_policies_attached_to_users.sh
│   ├── aws_iam_policies_granting_full_access.sh
│   ├── aws_iam_policies_unattached.sh
│   ├── aws_iam_policy_attachments.sh
│   ├── aws_iam_policy_delete.sh
│   ├── aws_iam_rename_user_accounts_domains.sh
│   ├── aws_iam_replace_access_key.sh
│   ├── aws_iam_users.sh
│   ├── aws_iam_users_access_key_age.sh
│   ├── aws_iam_users_access_key_age_report.sh
│   ├── aws_iam_users_access_key_last_used.sh
│   ├── aws_iam_users_access_key_last_used_report.sh
│   ├── aws_iam_users_last_used_report.sh
│   ├── aws_iam_users_mfa_active_report.sh
│   ├── aws_iam_users_mfa_serials.sh
│   ├── aws_iam_users_pw_last_used.sh
│   ├── aws_iam_users_without_mfa.sh
│   ├── aws_info.sh
│   ├── aws_info_all_profiles.sh
│   ├── aws_info_ec2.sh
│   ├── aws_info_ec2_all_profiles_csv.sh
│   ├── aws_info_ec2_csv.sh
│   ├── aws_ip_ranges.sh
│   ├── aws_kinesis_stream_names.sh
│   ├── aws_kms_key_rotation_enabled.sh
│   ├── aws_kube_creds.sh
│   ├── aws_kubectl.sh
│   ├── aws_logs.sh
│   ├── aws_logs_batch_jobs.sh
│   ├── aws_logs_ec2_spot.sh
│   ├── aws_logs_ecs_tasks.sh
│   ├── aws_meta.sh
│   ├── aws_nat_gateways_public_ips.sh
│   ├── aws_profile.sh
│   ├── aws_profile_config_add_if_missing.sh
│   ├── aws_profile_generate_direnvs.sh
│   ├── aws_rds_get_version.sh
│   ├── aws_rds_list.sh
│   ├── aws_rds_open_port_to_my_ip.sh
│   ├── aws_route53_check_ns_records.sh
│   ├── aws_s3_access_logging.sh
│   ├── aws_s3_account_block_public_access.sh
│   ├── aws_s3_bucket.sh
│   ├── aws_s3_buckets_block_public_access.sh
│   ├── aws_s3_check_account_public_blocked.sh
│   ├── aws_s3_check_buckets_public_blocked.sh
│   ├── aws_s3_delete_bucket_with_versions.sh
│   ├── aws_s3_sync.sh
│   ├── aws_secret_add.sh
│   ├── aws_secret_add_binary.sh
│   ├── aws_secret_get.sh
│   ├── aws_secret_list.sh
│   ├── aws_secret_update.sh
│   ├── aws_secret_update_binary.sh
│   ├── aws_spot_when_terminated.sh
│   ├── aws_sqs_check.sh
│   ├── aws_sqs_delete_messages.sh
│   ├── aws_ssm_put_param.sh
│   ├── aws_ssm_wait_for_command.sh
│   ├── aws_sso_account_id_names.sh
│   ├── aws_sso_accounts.sh
│   ├── aws_sso_accounts_missing_from_list.sh
│   ├── aws_sso_cache_expires.sh
│   ├── aws_sso_config_duplicate_profile_names.sh
│   ├── aws_sso_config_duplicate_sections.sh
│   ├── aws_sso_configs.sh
│   ├── aws_sso_configs_save.sh
│   ├── aws_sso_env_creds.sh
│   ├── aws_sso_role_arn.sh
│   ├── aws_sso_role_arns.sh
│   ├── aws_sso_ssh.sh
│   ├── aws_terraform_create_all.sh
│   ├── aws_terraform_create_atlantis_role.sh
│   ├── aws_terraform_create_credential.sh
│   ├── aws_terraform_create_dynamodb_table.sh
│   ├── aws_terraform_create_s3_bucket.sh
│   ├── aws_terraform_iam_grant_s3_dynamodb.sh
│   └── eksctl_cluster.sh
├── azure-pipelines.yml
├── azure_devops/
│   ├── azure_devops_api.sh
│   ├── azure_devops_disable_repos.sh
│   ├── azure_devops_foreach_repo.sh
│   └── azure_devops_to_github_migration.sh
├── bigdata/
│   ├── beeline.sh
│   ├── beeline_zk.sh
│   ├── cloudera_manager_api.sh
│   ├── cloudera_manager_impala_queries.sh
│   ├── cloudera_manager_impala_queries_ddl.sh
│   ├── cloudera_manager_impala_queries_exceptions.sh
│   ├── cloudera_manager_impala_queries_failed.sh
│   ├── cloudera_manager_impala_queries_metadata.sh
│   ├── cloudera_manager_impala_queries_metadata_errors.sh
│   ├── cloudera_manager_impala_queries_metadata_refresh.sh
│   ├── cloudera_manager_yarn_apps.sh
│   ├── cloudera_manager_yarn_apps_failed.sh
│   ├── cloudera_navigator_api.sh
│   ├── cloudera_navigator_audit_logs.sh
│   ├── cloudera_navigator_audit_logs_download.sh
│   ├── cloudera_navigator_audit_logs_download_retry.sh
│   ├── cloudera_navigator_audit_logs_export_postgresql.sh
│   ├── hadoop_random_node.sh
│   ├── hdfs_checksum.sh
│   ├── hdfs_checksum_crc.sh
│   ├── hdfs_checksum_crc_parallel.sh
│   ├── hdfs_checksum_parallel.sh
│   ├── hdfs_file_size.sh
│   ├── hdfs_file_size_including_replicas.sh
│   ├── hdfs_find_replication_factor_1.sh
│   ├── hdfs_set_replication_factor_3.sh
│   ├── hive_foreach_table.sh
│   ├── hive_list_databases.sh
│   ├── hive_list_tables.sh
│   ├── hive_tables_column_counts.sh
│   ├── hive_tables_locations.sh
│   ├── hive_tables_metadata.sh
│   ├── hive_tables_row_counts.sh
│   ├── impala_foreach_table.sh
│   ├── impala_list_databases.sh
│   ├── impala_list_tables.sh
│   ├── impala_shell.sh
│   ├── impala_tables_column_counts.sh
│   ├── impala_tables_locations.sh
│   ├── impala_tables_metadata.sh
│   ├── impala_tables_row_counts.sh
│   ├── zookeeper_client.sh
│   └── zookeeper_shell.sh
├── bin/
│   ├── bash_most_used_commands.sh
│   ├── bash_profile_bashrc.sh
│   ├── center.sh
│   ├── clean_caches.sh
│   ├── cocomo_man_years_estimate.sh
│   ├── copy_to_clipboard.sh
│   ├── crt_hash.sh
│   ├── crypto_dice_rolls.sh
│   ├── curl_auth.sh
│   ├── curl_with_cookies.sh
│   ├── debian_netinstall_pxesetup.sh
│   ├── decomment.sh
│   ├── delete_duplicate_files.sh
│   ├── delete_empty_dirs.sh
│   ├── diff_line_threshold.sh
│   ├── disable_swap.sh
│   ├── disk-read-random.fio
│   ├── disk-read-sequential.fio
│   ├── disk-tests.fio
│   ├── disk-write-random.fio
│   ├── disk-write-sequential.fio
│   ├── disk_speed_read_random_dd.sh
│   ├── disk_speed_read_random_fio.sh
│   ├── disk_speed_read_sequential_dd.sh
│   ├── disk_speed_read_sequential_fio.sh
│   ├── disk_speed_write_random_fio.sh
│   ├── disk_speed_write_sequential_dd.sh
│   ├── disk_speed_write_sequential_fio.sh
│   ├── download_url_file.sh
│   ├── elasticsearch_decommission_node.sh
│   ├── exec_interactive.sh
│   ├── file_extensions.sh
│   ├── find_broken_links.sh
│   ├── find_broken_symlinks.sh
│   ├── find_duplicate_files_by_checksum.sh
│   ├── find_duplicate_files_by_size.sh
│   ├── find_duplicate_lines.sh
│   ├── find_hanging_mount_point.sh
│   ├── find_hardlinks.sh
│   ├── find_lock.sh
│   ├── find_symlinks_to_other_directories.sh
│   ├── foreach_path_bin.sh
│   ├── grep_or_append.sh
│   ├── hackercase.sh
│   ├── headtail.sh
│   ├── hexencode.sh
│   ├── htmldecode.sh
│   ├── http_duplicate_urls.sh
│   ├── jsondiff.sh
│   ├── keycloak.sh
│   ├── ldap_group_recurse.sh
│   ├── ldap_user_recurse.sh
│   ├── ldapsearch.sh
│   ├── lint.sh
│   ├── linux_distro_versions.sh
│   ├── login.sh
│   ├── lowercase_filename.sh
│   ├── mac_backup_du_in_progress.sh
│   ├── mac_backup_exclude_paths.sh
│   ├── mac_backup_find_excluded_paths.sh
│   ├── mac_delete_local_snapshots.sh
│   ├── mac_diff_settings.sh
│   ├── mac_gif_preview.sh
│   ├── mac_iso_to_usb.sh
│   ├── mac_ramdisk.sh
│   ├── mac_restore_file.sh
│   ├── mac_rmdir.sh
│   ├── mv.sh
│   ├── network_gateway.sh
│   ├── open.sh
│   ├── oreilly_cover_download.sh
│   ├── organize_downloads.sh
│   ├── paste_diff_settings.sh
│   ├── paste_from_clipboard.sh
│   ├── paste_from_clipboard_upon_changes.sh
│   ├── path_revoke_world_writeable.sh
│   ├── pldd.sh
│   ├── processes_ram_sum.sh
│   ├── progress_dots.sh
│   ├── random_number.sh
│   ├── random_select.sh
│   ├── random_string.sh
│   ├── retry.sh
│   ├── run.sh
│   ├── sbtw
│   ├── scan_duplicate_macs.sh
│   ├── screen_terminal_to_clipboard.sh
│   ├── screen_terminal_to_stdout.sh
│   ├── shorten_text_selection.sh
│   ├── shred_file.sh
│   ├── shred_free_space.sh
│   ├── smart_quotes_replace.sh
│   ├── spasticcase.sh
│   ├── spasticcase2.sh
│   ├── split.sh
│   ├── sqlite.sh
│   ├── ssl_get_cert.sh
│   ├── ssl_verify_cert.sh
│   ├── ssl_verify_cert_by_ip.sh
│   ├── ssl_view_cert.sh
│   ├── text_filter_ending_substrings.sh
│   ├── tmux_horizontal.sh
│   ├── tmux_square.sh
│   ├── tmux_vertical.sh
│   ├── ubuntu_release_version.sh
│   ├── uniq_chars.sh
│   ├── url_extract_redirects.sh
│   ├── url_replace_redirects.sh
│   ├── urldecode.sh
│   ├── urlencode.sh
│   ├── urlencode_utf.sh
│   ├── urlextract.sh
│   ├── urlopen.sh
│   └── vault_pass.sh
├── bitbucket/
│   ├── bitbucket_api.sh
│   ├── bitbucket_disable_pipelines.sh
│   ├── bitbucket_enable_pipelines.sh
│   ├── bitbucket_foreach_repo.sh
│   ├── bitbucket_repo_disable_pipeline.sh
│   ├── bitbucket_repo_enable_pipeline.sh
│   ├── bitbucket_repo_set_description.sh
│   ├── bitbucket_repo_set_env_vars.sh
│   ├── bitbucket_ssh_add_public_keys.sh
│   ├── bitbucket_ssh_delete_public_keys.sh
│   ├── bitbucket_ssh_get_public_keys.sh
│   └── bitbucket_workspace_set_env_vars.sh
├── bitbucket-pipelines.yml
├── buddy.yml
├── buildkite/
│   ├── buildkite_agent.sh
│   ├── buildkite_agents.sh
│   ├── buildkite_api.sh
│   ├── buildkite_cancel_running_builds.sh
│   ├── buildkite_cancel_scheduled_builds.sh
│   ├── buildkite_create_pipeline.sh
│   ├── buildkite_foreach_pipeline.sh
│   ├── buildkite_get_pipeline.sh
│   ├── buildkite_patch_pipeline.sh
│   ├── buildkite_pipeline_disable_forked_pull_requests.sh
│   ├── buildkite_pipeline_set_skip_settings.sh
│   ├── buildkite_pipeline_skip_settings.sh
│   ├── buildkite_pipelines.sh
│   ├── buildkite_pipelines_vulnerable_forked_pull_requests.sh
│   ├── buildkite_rebuild_all_pipelines_last_cancelled.sh
│   ├── buildkite_rebuild_all_pipelines_last_failed.sh
│   ├── buildkite_rebuild_cancelled_builds.sh
│   ├── buildkite_rebuild_failed_builds.sh
│   ├── buildkite_rebuild_last_cancelled.sh
│   ├── buildkite_recreate_pipeline.sh
│   ├── buildkite_retry_jobs_dead_agents.sh
│   ├── buildkite_running_builds.sh
│   ├── buildkite_save_pipelines.sh
│   ├── buildkite_set_pipeline_description.sh
│   ├── buildkite_set_pipeline_description_from_github.sh
│   ├── buildkite_sync_pipeline_descriptions_from_github.sh
│   ├── buildkite_trigger.sh
│   ├── buildkite_trigger_all.sh
│   └── buildkite_update_pipeline.sh
├── checks/
│   ├── check_all.sh
│   ├── check_ansible_playbooks.sh
│   ├── check_aws_no_git_credentials.sh
│   ├── check_bash_arrays.sh
│   ├── check_bash_duplicate_defs.sh
│   ├── check_bash_references.sh
│   ├── check_bash_syntax.sh
│   ├── check_caches_clean.sh
│   ├── check_circleci_config.sh
│   ├── check_codefresh_config.sh
│   ├── check_concourse_config.sh
│   ├── check_cson.sh
│   ├── check_docker_clean.sh
│   ├── check_docker_compose.sh
│   ├── check_dockerfiles.sh
│   ├── check_drone_yml.sh
│   ├── check_duplicate_dependencies.sh
│   ├── check_duplicate_packages.sh
│   ├── check_git_commit_authors.sh
│   ├── check_git_no_merge_remnants.sh
│   ├── check_github_actions_workflow_injection.sh
│   ├── check_github_actions_workflows_without_checkout.sh
│   ├── check_github_codeowners.sh
│   ├── check_gitlab_ci_yml.sh
│   ├── check_gradle_build.sh
│   ├── check_groovyc.sh
│   ├── check_internet.sh
│   ├── check_javac.sh
│   ├── check_javascript_eslint.sh
│   ├── check_jenkinsfiles.sh
│   ├── check_json.sh
│   ├── check_kubernetes_yaml.sh
│   ├── check_license_exists.sh
│   ├── check_makefiles.sh
│   ├── check_maven_pom.sh
│   ├── check_no_suid_guid_shell_scripts.sh
│   ├── check_no_tabs.sh
│   ├── check_perl_syntax.sh
│   ├── check_python3_compat.sh
│   ├── check_python_asserts.sh
│   ├── check_python_exception_pass.sh
│   ├── check_python_misc.sh
│   ├── check_python_pep8.sh
│   ├── check_python_pylint.sh
│   ├── check_pytools.sh
│   ├── check_readme_badges.sh
│   ├── check_readme_exists.sh
│   ├── check_ruby_syntax.sh
│   ├── check_sbt_build.sh
│   ├── check_shebang_non_executable.sh
│   ├── check_shell_commands_dash_protections.sh
│   ├── check_shellcheck.sh
│   ├── check_shippable_readme_ids.sh
│   ├── check_sqlfluff.sh
│   ├── check_srcdir_references.sh
│   ├── check_ssh_keys_encrypted.sh
│   ├── check_symlinks.sh
│   ├── check_tests_run_qualified.sh
│   ├── check_tld_chars.sh
│   ├── check_travis_yml.sh
│   ├── check_url_links.sh
│   ├── check_vagrantfiles.sh
│   ├── check_whitespace.sh
│   ├── check_xml.sh
│   └── check_yaml.sh
├── cicd/
│   ├── .concourse.yml
│   ├── .gocd.yml
│   ├── buildspec.yml
│   ├── checkov_resource_count.sh
│   ├── checkov_resource_count_all.sh
│   ├── cloudbuild.yaml
│   ├── codefresh_cancel_delayed_builds.sh
│   ├── concourse.sh
│   ├── coveralls_latest.sh
│   ├── fly.sh
│   ├── generate_status_page.sh
│   ├── gerrit.sh
│   ├── gerrit_projects.sh
│   ├── gocd.sh
│   ├── gocd_api.sh
│   ├── octopus_api.sh
│   ├── run_latest_tests.sh
│   ├── run_tests.sh
│   ├── selenium_hub_wait_ready.sh
│   ├── sonarlint_generate_config.sh
│   ├── sync_bootstraps_to_adjacent_repos.sh
│   ├── sync_ci_to_adjacent_repos.sh
│   ├── sync_configs_to_adjacent_repos.sh
│   └── sync_github_actions_workflows_to_adjacent_repos.sh
├── circleci/
│   ├── circleci_api.sh
│   ├── circleci_context_delete_env_vars.sh
│   ├── circleci_context_set_env_vars.sh
│   ├── circleci_local_execute.sh
│   ├── circleci_project_delete_env_vars.sh
│   ├── circleci_project_set_env_vars.sh
│   └── circleci_public_ips.sh
├── cloudflare/
│   ├── cloudflare_api.sh
│   ├── cloudflare_custom_certificates.sh
│   ├── cloudflare_dns_record_create.sh
│   ├── cloudflare_dns_record_delete.sh
│   ├── cloudflare_dns_record_details.sh
│   ├── cloudflare_dns_record_update.sh
│   ├── cloudflare_dns_records.sh
│   ├── cloudflare_dns_records_all_zones.sh
│   ├── cloudflare_dnssec.sh
│   ├── cloudflare_firewall_access_rules.sh
│   ├── cloudflare_firewall_rules.sh
│   ├── cloudflare_foreach_account.sh
│   ├── cloudflare_foreach_zone.sh
│   ├── cloudflare_ip_ranges.sh
│   ├── cloudflare_purge_cache.sh
│   ├── cloudflare_ssl_verified.sh
│   ├── cloudflare_ssl_verified_all_zones.sh
│   └── cloudflare_zones.sh
├── codefresh.yml
├── codeship/
│   ├── codeship.yml
│   ├── codeship_api.sh
│   └── codeship_api_token.sh
├── configs/
│   ├── .Codefresh/
│   │   └── cli-config/
│   │       └── config.yaml
│   ├── .Xdefaults
│   ├── .Xmodmap
│   ├── .ansible.cfg
│   ├── .athenacli/
│   │   └── athenaclirc
│   ├── .aws/
│   │   ├── config
│   │   └── shell/
│   │       └── awsshellrc
│   ├── .checkov.yaml
│   ├── .config/
│   │   ├── flake8
│   │   ├── htop/
│   │   │   └── htoprc
│   │   ├── pycodestyle
│   │   ├── terminalizer/
│   │   │   └── config.yml
│   │   └── yamllint/
│   │       └── config
│   ├── .gemrc
│   ├── .grype.yaml
│   ├── .inputrc
│   ├── .luacheckrc
│   ├── .my.cnf
│   ├── .perlcritic_forbidden_modules
│   ├── .perlcriticrc
│   ├── .psqlrc
│   ├── .sawsrc
│   ├── .screenrc
│   ├── .sdkman/
│   │   └── etc/
│   │       └── config
│   ├── .sqliterc
│   ├── .terraformrc
│   ├── .tfdocs.d/
│   │   └── .terraform-docs.yml
│   ├── .tmux.conf
│   ├── .toprc
│   ├── .vimrc
│   ├── .wakatime.cfg
│   ├── .yamllint.yaml
│   ├── README.md
│   ├── clamd.conf
│   └── freshclam.conf
├── data/
│   ├── avro_tools.sh
│   ├── csv_header_indices.sh
│   ├── ini_config_add_if_missing.sh
│   ├── ini_config_duplicate_section_names.sh
│   ├── ini_config_duplicate_sections.sh
│   ├── ini_grep_section.sh
│   ├── json2yaml.sh
│   ├── lines_to_end.sh
│   ├── parquet_tools.sh
│   ├── wordcloud.sh
│   ├── wordcount.sh
│   └── yaml2json.sh
├── diagrams/
│   ├── d2.sh
│   ├── d2_generate_diagrams.sh
│   ├── mermaidjs_generate_diagrams.sh
│   └── python_mingrammer_generate_diagrams.sh
├── docker/
│   ├── docker_api.sh
│   ├── docker_build_hashref.sh
│   ├── docker_generate_status_page.sh
│   ├── docker_mount_build_exec.sh
│   ├── docker_package_check.sh
│   ├── docker_registry_get_image_manifest.sh
│   ├── docker_registry_list_images.sh
│   ├── docker_registry_list_tags.sh
│   ├── docker_registry_tag_image.sh
│   ├── dockerhub_api.sh
│   ├── dockerhub_build_status.sh
│   ├── dockerhub_list_tags.sh
│   ├── dockerhub_list_tags_by_last_updated.sh
│   ├── dockerhub_repo_set_description.sh
│   ├── dockerhub_repo_set_readme.sh
│   ├── dockerhub_search.sh
│   └── quay_api.sh
├── docker-compose/
│   ├── circleci.yml
│   ├── concourse.yml
│   ├── gerrit.yml
│   ├── gocd.yml
│   ├── jenkins.yml
│   ├── keycloak.yml
│   ├── octopus-deploy.env
│   ├── octopus-deploy.yml
│   ├── prometheus.yml
│   ├── teamcity.yml
│   └── wordpress.yml
├── drone/
│   ├── drone_api.sh
│   ├── drone_docker_runner.sh
│   └── drone_docker_server.sh
├── gcp/
│   ├── .customize_environment
│   ├── .gcloudignore
│   ├── bigquery_foreach_dataset.sh
│   ├── bigquery_foreach_table.sh
│   ├── bigquery_foreach_table_all_datasets.sh
│   ├── bigquery_generate_query_biggest_tables_across_datasets_by_row_count.sh
│   ├── bigquery_generate_query_biggest_tables_across_datasets_by_size.sh
│   ├── bigquery_list_datasets.sh
│   ├── bigquery_list_tables.sh
│   ├── bigquery_list_tables_all_datasets.sh
│   ├── bigquery_table_row_count.sh
│   ├── bigquery_tables_row_counts.sh
│   ├── bigquery_tables_row_counts_all_datasets.sh
│   ├── firebase_foreach_project.sh
│   ├── gce_foreach_vm.sh
│   ├── gce_host_ips.sh
│   ├── gce_instance_service_accounts.sh
│   ├── gce_is_preempted.sh
│   ├── gce_meta.sh
│   ├── gce_ssh.sh
│   ├── gce_ssh_keyscan.sh
│   ├── gce_when_preempted.sh
│   ├── gcp_ansible_create_credential.sh
│   ├── gcp_ci_build.sh
│   ├── gcp_ci_deploy_k8s.sh
│   ├── gcp_cli_create_credential.sh
│   ├── gcp_cloud_schedule_sql_exports.sh
│   ├── gcp_find_orphaned_disks.sh
│   ├── gcp_firewall_disable_default_rules.sh
│   ├── gcp_firewall_risky_rules.sh
│   ├── gcp_foreach_project.sh
│   ├── gcp_iam_identities_in_use.sh
│   ├── gcp_iam_roles_granted_to_identity.sh
│   ├── gcp_iam_roles_granted_too_widely.sh
│   ├── gcp_iam_roles_in_use.sh
│   ├── gcp_iam_roles_with_direct_user_grants.sh
│   ├── gcp_iam_serviceaccount_members.sh
│   ├── gcp_iam_serviceaccounts_without_permissions.sh
│   ├── gcp_iam_users_granted_directly.sh
│   ├── gcp_iam_workload_identities.sh
│   ├── gcp_info.sh
│   ├── gcp_info_accounts_secrets.sh
│   ├── gcp_info_all_projects.sh
│   ├── gcp_info_auth_config.sh
│   ├── gcp_info_bigdata.sh
│   ├── gcp_info_cloud_sql.sh
│   ├── gcp_info_cloud_sql_backups.sh
│   ├── gcp_info_cloud_sql_databases.sh
│   ├── gcp_info_cloud_sql_users.sh
│   ├── gcp_info_compute.sh
│   ├── gcp_info_gke.sh
│   ├── gcp_info_networking.sh
│   ├── gcp_info_projects.sh
│   ├── gcp_info_services.sh
│   ├── gcp_info_storage.sh
│   ├── gcp_info_tools.sh
│   ├── gcp_secret_add.sh
│   ├── gcp_secret_add_binary.sh
│   ├── gcp_secret_get.sh
│   ├── gcp_secret_label_k8s.sh
│   ├── gcp_secret_update.sh
│   ├── gcp_secrets_labels.sh
│   ├── gcp_secrets_to_kubernetes.sh
│   ├── gcp_secrets_to_kubernetes_multipart.sh
│   ├── gcp_secrets_update_label.sh
│   ├── gcp_service_account_credential_to_secret.sh
│   ├── gcp_service_account_members.sh
│   ├── gcp_service_accounts_credential_keys.sh
│   ├── gcp_service_accounts_credential_keys_age.sh
│   ├── gcp_service_accounts_credential_keys_expired.sh
│   ├── gcp_service_apis.sh
│   ├── gcp_spinnaker_create_credential.sh
│   ├── gcp_sql_backup.sh
│   ├── gcp_sql_create_readonly_service_account.sh
│   ├── gcp_sql_enable_automated_backups.sh
│   ├── gcp_sql_enable_point_in_time_recovery.sh
│   ├── gcp_sql_export.sh
│   ├── gcp_sql_grant_instances_gcs_object_creator.sh
│   ├── gcp_sql_list_databases.sh
│   ├── gcp_sql_proxy.sh
│   ├── gcp_sql_running_primaries.sh
│   ├── gcp_sql_service_accounts.sh
│   ├── gcp_terraform_create_credential.sh
│   ├── gcr_alternate_tags.sh
│   ├── gcr_delete_old_tags.sh
│   ├── gcr_list_tags.sh
│   ├── gcr_newest_image_tags.sh
│   ├── gcr_tag_branch.sh
│   ├── gcr_tag_datetime.sh
│   ├── gcr_tag_latest.sh
│   ├── gcr_tag_newest_image_as_latest.sh
│   ├── gcr_tags_old.sh
│   ├── gcr_tags_timestamps.sh
│   ├── gcs_bucket_project.sh
│   ├── gcs_curl_file.sh
│   ├── gke_firewall_rule_cert_manager.sh
│   ├── gke_firewall_rule_kubeseal.sh
│   ├── gke_kube_creds.sh
│   ├── gke_kubectl.sh
│   ├── gke_nodepool_drain.sh
│   ├── gke_nodepool_nodes.sh
│   ├── gke_nodepool_nodes2.sh
│   ├── gke_nodepool_taint.sh
│   └── gke_persistent_volume_disk_mappings.sh
├── git/
│   ├── git_askpass.sh
│   ├── git_branch_delete_squash_merged.sh
│   ├── git_clean_repos.sh
│   ├── git_diff_commit.sh
│   ├── git_files_in_history.sh
│   ├── git_files_last_modified.sh
│   ├── git_files_no_uncommitted_changes.sh
│   ├── git_filter_branch_fix_author.sh
│   ├── git_filter_repo_replace_text.sh
│   ├── git_foreach_branch.sh
│   ├── git_foreach_modified.sh
│   ├── git_foreach_repo.sh
│   ├── git_foreach_repo_replace_readme_actions.sh
│   ├── git_foreach_repo_update_readme.sh
│   ├── git_graph_commit_history_gnuplot.sh
│   ├── git_graph_commit_history_mermaidjs.sh
│   ├── git_graph_commit_times_gnuplot.sh
│   ├── git_graph_commit_times_gnuplot_all_repos.sh
│   ├── git_graph_commit_times_mermaidjs.sh
│   ├── git_graph_commit_times_mermaidjs_all_repos.sh
│   ├── git_grep_env_vars.sh
│   ├── git_log_empty_commits.sh
│   ├── git_log_me.sh
│   ├── git_log_me_added.sh
│   ├── git_merge_all.sh
│   ├── git_merge_branch.sh
│   ├── git_merge_master.sh
│   ├── git_merge_master_pull.sh
│   ├── git_origin_commit_count_to_push.sh
│   ├── git_origin_diff_to_push.sh
│   ├── git_origin_files_to_push.sh
│   ├── git_origin_line_count_to_push.sh
│   ├── git_origin_log_to_push.sh
│   ├── git_pull_make_repos.sh
│   ├── git_push_stats.sh
│   ├── git_remotes_add_origin_providers.sh
│   ├── git_remotes_set_https_creds_helpers.sh
│   ├── git_remotes_set_https_to_ssh.sh
│   ├── git_remotes_set_multi_origin.sh
│   ├── git_remotes_set_ssh_to_https.sh
│   ├── git_repos.sh
│   ├── git_repos_pull.sh
│   ├── git_repos_update.sh
│   ├── git_revert_line.sh
│   ├── git_review_push.sh
│   ├── git_set_dir_safe.sh
│   ├── git_submodules_update.sh
│   ├── git_submodules_update_repos.sh
│   ├── git_summary_line.sh
│   ├── git_sync_repos_upstream.sh
│   ├── git_tag_release.sh
│   ├── gitguardian_api.sh
│   ├── gitignore.io_api.sh
│   ├── precommit_run_changed_files.sh
│   └── update_gitignore.io.sh
├── github/
│   ├── github_actions_aws_create_load_credential.sh
│   ├── github_actions_delete_offline_runners.sh
│   ├── github_actions_foreach_workflow.sh
│   ├── github_actions_in_use.sh
│   ├── github_actions_in_use_across_repos.sh
│   ├── github_actions_in_use_repo.sh
│   ├── github_actions_latest_log.sh
│   ├── github_actions_log.sh
│   ├── github_actions_repo_actions_allow.sh
│   ├── github_actions_repo_env_set_secret.sh
│   ├── github_actions_repo_restrict_actions.sh
│   ├── github_actions_repo_secrets_overriding_org.sh
│   ├── github_actions_repo_set_secret.sh
│   ├── github_actions_repos_lockdown.sh
│   ├── github_actions_runner.sh
│   ├── github_actions_runner_local.sh
│   ├── github_actions_runner_token.sh
│   ├── github_actions_runners.sh
│   ├── github_actions_workflow_enable.sh
│   ├── github_actions_workflow_runs.sh
│   ├── github_actions_workflows.sh
│   ├── github_actions_workflows_cancel_all_runs.sh
│   ├── github_actions_workflows_cancel_waiting_runs.sh
│   ├── github_actions_workflows_disabled.sh
│   ├── github_actions_workflows_enable_all.sh
│   ├── github_actions_workflows_rerun_failed.sh
│   ├── github_actions_workflows_state.sh
│   ├── github_actions_workflows_status.sh
│   ├── github_actions_workflows_status2.sh
│   ├── github_actions_workflows_trigger_all.sh
│   ├── github_api.sh
│   ├── github_clone_or_pull_all_repos.sh
│   ├── github_download_release_file.sh
│   ├── github_download_release_jar.sh
│   ├── github_foreach_repo.sh
│   ├── github_forked_add_remote.sh
│   ├── github_forked_checkout_branch.sh
│   ├── github_generate_starcharts.md.sh
│   ├── github_generate_status_page.sh
│   ├── github_gpg_get_user_keys.sh
│   ├── github_graph_commit_times_gnuplot.sh
│   ├── github_graph_commit_times_mermaidjs.sh
│   ├── github_install_binary.sh
│   ├── github_invitations.sh
│   ├── github_ip_ranges.sh
│   ├── github_merge_branch.sh
│   ├── github_mirror_repos_to_aws_codecommit.sh
│   ├── github_mirror_repos_to_bitbucket.sh
│   ├── github_mirror_repos_to_gcp_source_repos.sh
│   ├── github_mirror_repos_to_gitlab.sh
│   ├── github_public_lines_of_code.sh
│   ├── github_pull_merge_trunk.sh
│   ├── github_pull_request_create.sh
│   ├── github_pull_request_preview.sh
│   ├── github_purge_camo_cache.sh
│   ├── github_push_pr.sh
│   ├── github_push_pr_preview.sh
│   ├── github_release.sh
│   ├── github_remote_set_upstream.sh
│   ├── github_repo_add_collaborator.sh
│   ├── github_repo_check_pat_token.sh
│   ├── github_repo_collaborators.sh
│   ├── github_repo_description.sh
│   ├── github_repo_find_files.sh
│   ├── github_repo_fork_sync.sh
│   ├── github_repo_fork_update.sh
│   ├── github_repo_latest_release.sh
│   ├── github_repo_latest_release_filter.sh
│   ├── github_repo_protect_branches.sh
│   ├── github_repo_stars.sh
│   ├── github_repo_teams.sh
│   ├── github_repos_disable_rebase.sh
│   ├── github_repos_disable_wiki.sh
│   ├── github_repos_find_files.sh
│   ├── github_repos_not_in_terraform.sh
│   ├── github_repos_public.sh
│   ├── github_repos_sync_status.sh
│   ├── github_repos_with_few_teams.sh
│   ├── github_repos_with_few_users.sh
│   ├── github_repos_without_branch_protections.sh
│   ├── github_ssh_add_public_keys.sh
│   ├── github_ssh_delete_public_keys.sh
│   ├── github_ssh_get_public_keys.sh
│   ├── github_ssh_get_user_public_keys.sh
│   ├── github_ssh_get_user_public_keys2.sh
│   ├── github_sync_repo_descriptions.sh
│   ├── github_tag_hashref.sh
│   ├── github_teams_not_idp_synced.sh
│   ├── github_teams_not_in_terraform.sh
│   ├── github_url_clipboard.sh
│   ├── github_user_followers.sh
│   ├── github_user_repos_count.sh
│   ├── github_user_repos_forks.sh
│   ├── github_user_repos_stars.sh
│   └── gitio.sh
├── gitlab/
│   ├── gitlab_api.sh
│   ├── gitlab_foreach_repo.sh
│   ├── gitlab_get_user_ssh_public_keys.sh
│   ├── gitlab_get_user_ssh_public_keys2.sh
│   ├── gitlab_group_set_env_vars.sh
│   ├── gitlab_install_binary.sh
│   ├── gitlab_project_create_import.sh
│   ├── gitlab_project_latest_release.sh
│   ├── gitlab_project_mirrors.sh
│   ├── gitlab_project_protect_branches.sh
│   ├── gitlab_project_set_description.sh
│   ├── gitlab_project_set_env_vars.sh
│   ├── gitlab_pull_mirror.sh
│   ├── gitlab_push_mr.sh
│   ├── gitlab_push_mr_preview.sh
│   ├── gitlab_ssh_add_public_keys.sh
│   ├── gitlab_ssh_delete_public_keys.sh
│   ├── gitlab_ssh_get_public_keys.sh
│   └── gitlab_validate_ci_yaml.sh
├── hadolint.yaml
├── images/
│   └── README.md
├── install/
│   ├── download_avro_tools.sh
│   ├── download_azul_openjdk.sh
│   ├── download_bytecode_viewer_jar.sh
│   ├── download_cfr_jar.sh
│   ├── download_jd_gui_jar.sh
│   ├── download_mssql_jdbc_jar.sh
│   ├── download_mysql_jdbc_jar.sh
│   ├── download_openjdk.sh
│   ├── download_parquet_tools.sh
│   ├── download_postgres_jdbc_jar.sh
│   ├── download_procyon_jar.sh
│   ├── download_vertica_jar.sh
│   ├── getawless.sh
│   ├── install_android_commandlinetools.sh
│   ├── install_android_sdk.sh
│   ├── install_ansible.sh
│   ├── install_appveyor_byoc.sh
│   ├── install_argocd.sh
│   ├── install_awless.sh
│   ├── install_aws_cli.sh
│   ├── install_aws_ebcli.sh
│   ├── install_aws_sam_cli.sh
│   ├── install_azure_cli.sh
│   ├── install_azure_devops_cli.sh
│   ├── install_bazel.sh
│   ├── install_bazelisk.sh
│   ├── install_buildkite.sh
│   ├── install_cert_manager_cli.sh
│   ├── install_circleci.sh
│   ├── install_circleci_runner.sh
│   ├── install_clairctl.sh
│   ├── install_cliclick.sh
│   ├── install_cloud_sql_proxy.sh
│   ├── install_cloudbees.sh
│   ├── install_coder_cli.sh
│   ├── install_container-diff.sh
│   ├── install_crictl.sh
│   ├── install_d2.sh
│   ├── install_datree.sh
│   ├── install_diff-so-fancy.sh
│   ├── install_direnv.sh
│   ├── install_docker_buildx.sh
│   ├── install_docker_compose.sh
│   ├── install_docker_scan.sh
│   ├── install_dockerhub_cli.sh
│   ├── install_dockle.sh
│   ├── install_doctl.sh
│   ├── install_drone.sh
│   ├── install_eksctl.sh
│   ├── install_eksup.sh
│   ├── install_epel_repo.sh
│   ├── install_etcd.sh
│   ├── install_firebase_cli.sh
│   ├── install_fly.sh
│   ├── install_fossa_cli.sh
│   ├── install_gcloud_sdk.sh
│   ├── install_github_cli.sh
│   ├── install_github_codeql.sh
│   ├── install_github_ssh_keys.sh
│   ├── install_gitlab_cli.sh
│   ├── install_golang.sh
│   ├── install_gonogo.sh
│   ├── install_gradle.sh
│   ├── install_groovy.sh
│   ├── install_grype.sh
│   ├── install_helm.sh
│   ├── install_homebrew.sh
│   ├── install_infoblox_ova.sh
│   ├── install_intellij_plugins.sh
│   ├── install_java.sh
│   ├── install_jfrog_cli.sh
│   ├── install_jx.sh
│   ├── install_k3d.sh
│   ├── install_k3s.sh
│   ├── install_k6.sh
│   ├── install_keeper_cli.sh
│   ├── install_kics.sh
│   ├── install_kind.sh
│   ├── install_knative_cli.sh
│   ├── install_kops.sh
│   ├── install_kubectl.sh
│   ├── install_kubectl_plugin_cert_manager.sh
│   ├── install_kubectl_plugin_convert.sh
│   ├── install_kubectl_plugin_krew.sh
│   ├── install_kubent.sh
│   ├── install_kubescape.sh
│   ├── install_kubeseal.sh
│   ├── install_kubevious.sh
│   ├── install_kustomize.sh
│   ├── install_maven.sh
│   ├── install_mermaidjs.sh
│   ├── install_minikube.sh
│   ├── install_minishift.sh
│   ├── install_mousetools.sh
│   ├── install_ngrok.sh
│   ├── install_nova.sh
│   ├── install_octo.sh
│   ├── install_oh-my-zsh.sh
│   ├── install_openssh.sh
│   ├── install_oracle_client.sh
│   ├── install_oracle_sql_developer.sh
│   ├── install_oracle_sqlcl.sh
│   ├── install_packer.sh
│   ├── install_parquet-tools.sh
│   ├── install_pluto.sh
│   ├── install_polaris.sh
│   ├── install_powershell.sh
│   ├── install_powershell_debian.sh
│   ├── install_powershell_rhel.sh
│   ├── install_powershell_ubuntu.sh
│   ├── install_prometheus.sh
│   ├── install_prometheus_alertmanager.sh
│   ├── install_prometheus_blackbox_exporter.sh
│   ├── install_prometheus_consul_exporter.sh
│   ├── install_prometheus_graphite_exporter.sh
│   ├── install_prometheus_memcached_exporter.sh
│   ├── install_prometheus_mysqld_exporter.sh
│   ├── install_prometheus_node_exporter.sh
│   ├── install_prometheus_push_gateway.sh
│   ├── install_prometheus_statsd_exporter.sh
│   ├── install_promlens.sh
│   ├── install_pulumi_cli.sh
│   ├── install_rancher_cli.sh
│   ├── install_rpmforge.sh
│   ├── install_rvm.sh
│   ├── install_sbt.sh
│   ├── install_sdkman.sh
│   ├── install_sdkman_all_sdks.sh
│   ├── install_semaphore_ci.sh
│   ├── install_serverless.sh
│   ├── install_spotifycontrol.sh
│   ├── install_squirrel_sql.sh
│   ├── install_syft.sh
│   ├── install_talosctl.sh
│   ├── install_terraform.sh
│   ├── install_terraformer.sh
│   ├── install_terragrunt.sh
│   ├── install_tfenv.sh
│   ├── install_tfsec.sh
│   ├── install_tgswitch.sh
│   ├── install_tkn.sh
│   ├── install_travis.sh
│   ├── install_trivy.sh
│   ├── install_vertica_vsql_client.sh
│   ├── install_vertica_vsql_client_rpm.sh
│   ├── install_vundle.sh
│   ├── install_wercker_cli.sh
│   └── install_yq.sh
├── internet/
│   ├── 0x0.sh
│   ├── atlassian_ip_ranges.sh
│   ├── catbox.sh
│   ├── datadog_api.sh
│   ├── digital_ocean_api.sh
│   ├── dnsjson.sh
│   ├── domains_subdomains_environments.sh
│   ├── dpaste.sh
│   ├── file.io.sh
│   ├── google_maps_link.sh
│   ├── imgur.sh
│   ├── jira_api.sh
│   ├── kong_api.sh
│   ├── litterbox.sh
│   ├── ngrok_api.sh
│   ├── pastebin.sh
│   ├── shields_embed_logo.sh
│   ├── termbin.sh
│   ├── traefik_api.sh
│   ├── wordpress.htaccess
│   ├── wordpress.sh
│   ├── wordpress_api.sh
│   ├── wordpress_plugins_markdown.sh
│   └── wordpress_posts_without_category_tags.sh
├── ipaas/
│   └── make_api.sh
├── java/
│   ├── bytecode_viewer.sh
│   ├── cfr.sh
│   ├── java_decompile_jar.sh
│   ├── java_show_classpath.sh
│   ├── jd_gui.sh
│   ├── jvm_heaps.sh
│   ├── jvm_heaps_total_mb.sh
│   └── procyon.sh
├── jenkins/
│   ├── README.md
│   ├── jenkins.sh
│   ├── jenkins_api.sh
│   ├── jenkins_builds.sh
│   ├── jenkins_clear_build_history.groovy
│   ├── jenkins_clear_build_history_all_jobs.groovy
│   ├── jenkins_cli.sh
│   ├── jenkins_count_jobs.groovy
│   ├── jenkins_create_job_check_gcp_serviceaccount.sh
│   ├── jenkins_create_job_parallel_test_runs.sh
│   ├── jenkins_create_run_job.sh
│   ├── jenkins_cred_add_cert.sh
│   ├── jenkins_cred_add_kubernetes_sa.sh
│   ├── jenkins_cred_add_secret_file.sh
│   ├── jenkins_cred_add_secret_text.sh
│   ├── jenkins_cred_add_ssh_key.sh
│   ├── jenkins_cred_add_user_pass.sh
│   ├── jenkins_cred_cli_add_cert.sh
│   ├── jenkins_cred_cli_add_kubernetes_sa.sh
│   ├── jenkins_cred_cli_add_secret_file.sh
│   ├── jenkins_cred_cli_add_secret_text.sh
│   ├── jenkins_cred_cli_add_ssh_key.sh
│   ├── jenkins_cred_cli_add_user_pass.sh
│   ├── jenkins_cred_cli_delete.sh
│   ├── jenkins_cred_cli_list.sh
│   ├── jenkins_cred_cli_set_cert.sh
│   ├── jenkins_cred_cli_set_kubernetes_sa.sh
│   ├── jenkins_cred_cli_set_secret_file.sh
│   ├── jenkins_cred_cli_set_secret_text.sh
│   ├── jenkins_cred_cli_set_ssh_key.sh
│   ├── jenkins_cred_cli_set_user_pass.sh
│   ├── jenkins_cred_cli_update_cert.sh
│   ├── jenkins_cred_cli_update_kubernetes_sa.sh
│   ├── jenkins_cred_cli_update_secret_file.sh
│   ├── jenkins_cred_cli_update_secret_text.sh
│   ├── jenkins_cred_cli_update_ssh_key.sh
│   ├── jenkins_cred_cli_update_user_pass.sh
│   ├── jenkins_cred_delete.sh
│   ├── jenkins_cred_get.sh
│   ├── jenkins_cred_list.sh
│   ├── jenkins_cred_set_cert.sh
│   ├── jenkins_cred_set_kubernetes_sa.sh
│   ├── jenkins_cred_set_secret_file.sh
│   ├── jenkins_cred_set_secret_text.sh
│   ├── jenkins_cred_set_ssh_key.sh
│   ├── jenkins_cred_set_user_pass.sh
│   ├── jenkins_cred_update_cert.sh
│   ├── jenkins_cred_update_kubernetes_sa.sh
│   ├── jenkins_cred_update_secret_file.sh
│   ├── jenkins_cred_update_secret_text.sh
│   ├── jenkins_cred_update_ssh_key.sh
│   ├── jenkins_cred_update_user_pass.sh
│   ├── jenkins_creds_cli_xml_dump.sh
│   ├── jenkins_foreach_job.sh
│   ├── jenkins_foreach_job_cli.sh
│   ├── jenkins_job_config.sh
│   ├── jenkins_job_description.sh
│   ├── jenkins_job_disable.groovy
│   ├── jenkins_job_disable.sh
│   ├── jenkins_job_enable.sh
│   ├── jenkins_job_trigger.sh
│   ├── jenkins_job_trigger_with_params.sh
│   ├── jenkins_jobs.groovy
│   ├── jenkins_jobs.sh
│   ├── jenkins_jobs_disable.sh
│   ├── jenkins_jobs_disabled.groovy
│   ├── jenkins_jobs_download_configs.sh
│   ├── jenkins_jobs_download_configs_cli.sh
│   ├── jenkins_jobs_enable.sh
│   ├── jenkins_jobs_status.groovy
│   ├── jenkins_password.sh
│   └── jenkins_plugins_latest_versions.sh
├── kafka/
│   ├── kafka_acls.sh
│   ├── kafka_cli_jaas.conf
│   ├── kafka_configs.sh
│   ├── kafka_console_consumer.sh
│   ├── kafka_console_producer.sh
│   ├── kafka_consumer_groups.sh
│   ├── kafka_consumer_perf_test.sh
│   ├── kafka_producer_perf_test.sh
│   └── kafka_topics.sh
├── kics.config
├── kubernetes/
│   ├── argocd_apps_sync.sh
│   ├── argocd_apps_wait_sync.sh
│   ├── argocd_auto_sync.sh
│   ├── argocd_generate_resource_whitelist.sh
│   ├── argocd_namespace_resource_whitelist.sh
│   ├── argocd_password.sh
│   ├── curl_k8s_ingress.sh
│   ├── datree_kustomize_all.sh
│   ├── helm_template.sh
│   ├── kubeadm_join_cmd.sh
│   ├── kubeadm_join_cmd2.sh
│   ├── kubectl.sh
│   ├── kubectl_alpine.sh
│   ├── kubectl_busybox.sh
│   ├── kubectl_container_count.sh
│   ├── kubectl_container_counts.sh
│   ├── kubectl_create_namespaces.sh
│   ├── kubectl_curl.sh
│   ├── kubectl_delete_empty_namespaces.sh
│   ├── kubectl_deployment_pods.sh
│   ├── kubectl_diff_apply.sh
│   ├── kubectl_dnsutils.sh
│   ├── kubectl_empty_namespaces.sh
│   ├── kubectl_exec.sh
│   ├── kubectl_exec2.sh
│   ├── kubectl_gcloud_sdk.sh
│   ├── kubectl_get_all.sh
│   ├── kubectl_get_annotation.sh
│   ├── kubectl_image_counts.sh
│   ├── kubectl_image_deployments.sh
│   ├── kubectl_images.sh
│   ├── kubectl_jobs_delete_stuck.sh
│   ├── kubectl_jobs_stuck.sh
│   ├── kubectl_kv_to_secret.sh
│   ├── kubectl_logs.sh
│   ├── kubectl_node_labels.sh
│   ├── kubectl_node_taints.sh
│   ├── kubectl_pod_count.sh
│   ├── kubectl_pod_ips.sh
│   ├── kubectl_pod_labels.sh
│   ├── kubectl_pods_colocated.sh
│   ├── kubectl_pods_dump_all.sh
│   ├── kubectl_pods_dump_jstacks.sh
│   ├── kubectl_pods_dump_logs.sh
│   ├── kubectl_pods_dump_stats.sh
│   ├── kubectl_pods_important.sh
│   ├── kubectl_pods_per_node.sh
│   ├── kubectl_pods_running_with_labels.sh
│   ├── kubectl_port_forward.sh
│   ├── kubectl_port_forward_spark.sh
│   ├── kubectl_rerun_job.sh
│   ├── kubectl_restart.sh
│   ├── kubectl_rollout_history_all_deployments.sh
│   ├── kubectl_run_sa.sh
│   ├── kubectl_secret_values.sh
│   ├── kubectl_secrets_annotate_to_be_sealed.sh
│   ├── kubectl_secrets_download.sh
│   ├── kubectl_secrets_not_sealed.sh
│   ├── kubectl_secrets_to_be_sealed.sh
│   ├── kubernetes_api.sh
│   ├── kubernetes_autoscaler_release.sh
│   ├── kubernetes_check_objects_namespaced.sh
│   ├── kubernetes_delete_stuck_namespace.sh
│   ├── kubernetes_etcd_backup.sh
│   ├── kubernetes_foreach_context.sh
│   ├── kubernetes_foreach_namespace.sh
│   ├── kubernetes_info.sh
│   ├── kubernetes_nodes_ssh_dump_logs.sh
│   ├── kubernetes_resource_types.sh
│   ├── kubernetes_secret_to_external_secret_gcp.sh
│   ├── kubernetes_secret_to_sealed_secret.sh
│   ├── kubernetes_secrets_compare_gcp_secret_manager.sh
│   ├── kubernetes_secrets_to_external_secrets_gcp.sh
│   ├── kubernetes_secrets_to_sealed_secrets.sh
│   ├── kubernetes_yaml_strip_live_fields.sh
│   ├── kustomize_check_objects_namespaced.sh
│   ├── kustomize_diff_apply.sh
│   ├── kustomize_diff_branch.sh
│   ├── kustomize_install_helm_charts.sh
│   ├── kustomize_materialize.sh
│   ├── kustomize_parse_helm_charts.sh
│   ├── kustomize_update_helm_chart_versions.sh
│   ├── pluto_detect_helm_materialize.sh
│   ├── pluto_detect_kubectl_dump_objects.sh
│   ├── pluto_detect_kustomize_materialize.sh
│   ├── rancher_api.sh
│   └── rancher_kube_creds.sh
├── lib/
│   ├── README.md
│   ├── args_extract.sh
│   ├── aws.sh
│   ├── bitbucket.sh
│   ├── ci.sh
│   ├── cloudera_manager.sh
│   ├── cloudera_navigator.sh
│   ├── dbshell.sh
│   ├── docker.sh
│   ├── dockerfile_keywords.txt
│   ├── excluded.sh
│   ├── gcp.sh
│   ├── gcp_ci.sh
│   ├── git.sh
│   ├── github.sh
│   ├── gitlab.sh
│   ├── kubernetes.sh
│   ├── mac.sh
│   ├── mp3.sh
│   ├── os.sh
│   ├── packages.sh
│   ├── perl.sh
│   ├── python.sh
│   ├── ruby.sh
│   ├── spotify.sh
│   ├── sql.sh
│   ├── travis.sh
│   ├── utils-bourne.sh
│   └── utils.sh
├── markdown/
│   ├── markdown_columns_to_table.sh
│   ├── markdown_generate_index.sh
│   ├── markdown_list_indentations.sh
│   ├── markdown_octocat_github_links.sh
│   ├── markdown_replace_index.sh
│   ├── markdown_replace_links_with_jsdelivr.sh
│   ├── markdown_replace_repos.sh
│   └── mdl_list_indentations.sh
├── media/
│   ├── asciinema.sh
│   ├── avi_to_mp4.sh
│   ├── avif_to_png.sh
│   ├── image_join_vertical.sh
│   ├── image_reduce_quality.sh
│   ├── image_shrink.sh
│   ├── image_to_png.sh
│   ├── image_trim_pixels.sh
│   ├── imageopen.sh
│   ├── mkv_to_mp4.sh
│   ├── mp3_set_album.sh
│   ├── mp3_set_artist.sh
│   ├── mp3_set_track_name.sh
│   ├── mp3_set_track_order.sh
│   ├── svg_to_png.sh
│   ├── terminalizer.sh
│   ├── ttygif.sh
│   ├── video_to_720p_mp4.sh
│   ├── vidopen.sh
│   ├── webp_to_png.sh
│   ├── youtube_download_channel.sh
│   └── youtube_download_video.sh
├── monitoring/
│   ├── dump_stats.sh
│   ├── log_timestamp_large_intervals.sh
│   ├── prometheus.sh
│   ├── prometheus_docker.sh
│   ├── prometheus_node_exporter.sh
│   ├── ssh_dump_logs.sh
│   └── ssh_dump_stats.sh
├── mysql/
│   ├── mariadb.sh
│   ├── mariadb_test_scripts.sh
│   ├── mysql.sh
│   ├── mysql_foreach_table.sh
│   ├── mysql_list_databases.sh
│   ├── mysql_list_tables.sh
│   ├── mysql_tables_row_counts.sh
│   ├── mysql_test_scripts.sh
│   └── mysqld.sh
├── packages/
│   ├── apk_filter_installed.sh
│   ├── apk_filter_not_installed.sh
│   ├── apk_install_packages.sh
│   ├── apk_install_packages_if_absent.sh
│   ├── apk_remove_packages.sh
│   ├── apk_upgrade_packages_if_outdated.sh
│   ├── apt_install_packages.sh
│   ├── apt_install_packages_if_absent.sh
│   ├── apt_remove_packages.sh
│   ├── apt_set_lock_timeout.sh
│   ├── apt_upgrade_packages_if_outdated.sh
│   ├── apt_wait.sh
│   ├── brew_filter_in_setup.sh
│   ├── brew_filter_installed.sh
│   ├── brew_filter_not_in_setup.sh
│   ├── brew_filter_not_installed.sh
│   ├── brew_install_packages.sh
│   ├── brew_install_packages_if_absent.sh
│   ├── brew_package_owns.sh
│   ├── brew_upgrade_packages.sh
│   ├── brew_upgrade_packages_if_outdated.sh
│   ├── debs_filter_installed.sh
│   ├── debs_filter_not_installed.sh
│   ├── golang_install.sh
│   ├── golang_install_if_absent.sh
│   ├── golang_rm_binaries.sh
│   ├── install_binary.sh
│   ├── install_packages.sh
│   ├── install_packages_if_absent.sh
│   ├── nodejs_npm_install.sh
│   ├── nodejs_npm_install_if_absent.sh
│   ├── rpms_filter_installed.sh
│   ├── rpms_filter_not_installed.sh
│   ├── ruby_gem_install.sh
│   ├── ruby_gem_install_if_absent.sh
│   ├── upgrade_packages_if_outdated.sh
│   ├── yum_install_packages.sh
│   ├── yum_install_packages_if_absent.sh
│   ├── yum_remove_packages.sh
│   └── yum_upgrade_packages_if_outdated.sh
├── perl/
│   ├── perl_cpanm_install.sh
│   ├── perl_cpanm_install_if_absent.sh
│   ├── perl_cpanm_reinstall_all.sh
│   ├── perl_find_duplicate_cpan_requirements.sh
│   ├── perl_find_library_executable.sh
│   ├── perl_find_library_path.sh
│   ├── perl_find_unused_cpan_modules.sh
│   ├── perl_generate_fatpacks.sh
│   ├── perl_generate_par_binaries.sh
│   └── perlpath.sh
├── pingdom/
│   ├── pingdom_api.sh
│   ├── pingdom_check_latency_by_hour.sh
│   ├── pingdom_check_outages.sh
│   ├── pingdom_checks.sh
│   ├── pingdom_checks_average_response_times.sh
│   ├── pingdom_checks_latency_by_hour.sh
│   ├── pingdom_checks_outages.sh
│   ├── pingdom_foreach_check.sh
│   └── pingdom_sms_credits.sh
├── postgres/
│   ├── postgres.sh
│   ├── postgres_foreach_table.sh
│   ├── postgres_foreach_table_timeout.sh
│   ├── postgres_list_databases.sh
│   ├── postgres_list_schemas.sh
│   ├── postgres_list_tables.sh
│   ├── postgres_tables_row_counts.sh
│   ├── postgres_test_scripts.sh
│   ├── psql.sh
│   └── psql_colorized.sh
├── python/
│   ├── pygmentize.sh
│   ├── python_compile.sh
│   ├── python_find_duplicate_pip_requirements.sh
│   ├── python_find_library_executable.sh
│   ├── python_find_library_path.sh
│   ├── python_find_unused_pip_modules.sh
│   ├── python_indices.sh
│   ├── python_pip_install.sh
│   ├── python_pip_install_for_script.sh
│   ├── python_pip_install_if_absent.sh
│   ├── python_pip_reinstall_all_modules.sh
│   ├── python_pyinstaller.sh
│   ├── python_pypi_versions.sh
│   ├── python_translate_import_to_module.sh
│   ├── python_translate_module_to_import.sh
│   └── pythonpath.sh
├── requirements.txt
├── resources/
│   ├── oreilly-animals.json
│   ├── pipreqs_mapping.txt
│   ├── tabs_ignore.txt
│   └── whitespace_ignore.txt
├── scalastyle_config.xml
├── scripts/
│   ├── README.md
│   ├── git_capitalize_urls.sh
│   ├── spotify_commit_playlists.sh
│   ├── spotify_commit_rename_playlist.sh
│   ├── spotify_rename_playlist_files.sh
│   └── update_bash_tools_references.sh
├── search/
│   ├── solr_api.sh
│   ├── solr_collection_check_exists.sh
│   └── solr_collection_create_if_not_exists.sh
├── setup/
│   ├── Hari.terminal
│   ├── R-packages.txt
│   ├── README.md
│   ├── alternatives_set_python.sh
│   ├── apk-packages-desktop.txt
│   ├── apk-packages-optional.txt
│   ├── apk-packages.txt
│   ├── atom-packages.txt
│   ├── bootstrap.sh
│   ├── brew-packages-desktop-casks.txt
│   ├── brew-packages-desktop-taps.txt
│   ├── brew-packages-desktop.txt
│   ├── brew-packages-ignore.txt
│   ├── brew-packages.txt
│   ├── brew_fix_openssl_dependencies.sh
│   ├── brew_packages_not_saved.sh
│   ├── ccmenu_cp_plist.sh
│   ├── ccmenu_setup.sh
│   ├── ci.txt
│   ├── ci_bootstrap.sh
│   ├── ci_git_set_dir_safe.sh
│   ├── cpan-packages-desktop.txt
│   ├── cpan-requirements-optional.txt
│   ├── cpan-requirements.txt
│   ├── deb-packages-desktop.txt
│   ├── deb-packages-optional.txt
│   ├── deb-packages.txt
│   ├── debian.experimental.pref
│   ├── debian.stable.pref
│   ├── debian.testing.pref
│   ├── debian.unstable.pref
│   ├── docker-images.txt
│   ├── docker_bootstrap.sh
│   ├── download_cassandra.sh
│   ├── download_openjdk11.sh
│   ├── files.txt
│   ├── gem-packages-desktop.txt
│   ├── gem-packages.txt
│   ├── go-packages-desktop.txt
│   ├── gocd_config_repo.json
│   ├── intellij-plugins.txt
│   ├── jenkins-job-check-gcp-serviceaccount.xml
│   ├── jenkins-job-sleep-parallel-parameterized.xml
│   ├── jenkins-job.xml
│   ├── jenkins-plugins.txt
│   ├── linux_desktop.sh
│   ├── mac_delete_routes_on_interface.sh
│   ├── mac_desktop.sh
│   ├── mac_diff_settings.sh
│   ├── mac_settings.sh
│   ├── mac_spotlight_config_optimize.sh
│   ├── mas-packages.txt
│   ├── npm-packages-desktop.txt
│   ├── npm-packages.txt
│   ├── pip-packages-desktop.txt
│   ├── pip-packages-mac.txt
│   ├── pip_fix_version.sh
│   ├── portage-packages-desktop.txt
│   ├── portage-packages-dockapps.txt
│   ├── portage-packages-extras.txt
│   ├── portage-packages-server.txt
│   ├── postgresql.conf
│   ├── prometheus.yml
│   ├── python_install_snakebite.sh
│   ├── python_mac_upgrade_ssl_fix.sh
│   ├── repos.txt
│   ├── rpm-packages-desktop.txt
│   ├── rpm-packages-optional.txt
│   ├── rpm-packages.txt
│   ├── setup_codefresh.sh
│   ├── shell_link.sh
│   ├── shell_unlink.sh
│   ├── squirrelsql-install-options.xml
│   ├── teamcity/
│   │   └── teamcity-database.properties
│   ├── teamcity-mysql-setup.sql
│   ├── upgrade_gradle_wrapper.sh
│   └── which_python_installed.sh
├── shippable/
│   ├── shippable.yml
│   ├── shippable_account_id.sh
│   ├── shippable_api.sh
│   ├── shippable_builds.sh
│   ├── shippable_project_builds.sh
│   └── shippable_projects.sh
├── sonar-project.properties
├── spotify/
│   ├── spotify_add_artist_to_backlog_playlist.sh
│   ├── spotify_add_to_playlist.sh
│   ├── spotify_api.sh
│   ├── spotify_api_token.sh
│   ├── spotify_artist_tracks.sh
│   ├── spotify_artists_followed.sh
│   ├── spotify_artists_followed_uri.sh
│   ├── spotify_artists_followed_uri_name.sh
│   ├── spotify_backup.sh
│   ├── spotify_backup_artists_followed.sh
│   ├── spotify_backup_playlist.sh
│   ├── spotify_backup_playlists.sh
│   ├── spotify_backup_playlists_list.sh
│   ├── spotify_callback_openssl.cnf
│   ├── spotify_create_playlist.sh
│   ├── spotify_delete_any_duplicates_in_playlist.sh
│   ├── spotify_delete_duplicate_track_uris_in_playlist.sh
│   ├── spotify_delete_duplicate_tracks_in_playlists.sh
│   ├── spotify_delete_from_playlist.sh
│   ├── spotify_delete_from_playlist_if_in_other_playlists.sh
│   ├── spotify_delete_from_playlist_if_track_in_other_playlists.sh
│   ├── spotify_duplicate_tracks_in_playlist.sh
│   ├── spotify_duplicate_uri_in_playlist.sh
│   ├── spotify_filename_to_playlist.sh
│   ├── spotify_follow_artists.sh
│   ├── spotify_follow_liked_artists.sh
│   ├── spotify_follow_top_artists.sh
│   ├── spotify_foreach_playlist.sh
│   ├── spotify_liked_artists.sh
│   ├── spotify_liked_artists_uri.sh
│   ├── spotify_liked_tracks.sh
│   ├── spotify_liked_tracks_uri.sh
│   ├── spotify_liked_uri_artist_track.sh
│   ├── spotify_playlist_artists.sh
│   ├── spotify_playlist_id_to_name.sh
│   ├── spotify_playlist_json.sh
│   ├── spotify_playlist_name_to_id.sh
│   ├── spotify_playlist_snapshot_id.sh
│   ├── spotify_playlist_to_filename.sh
│   ├── spotify_playlist_top_artists.sh
│   ├── spotify_playlist_tracks.sh
│   ├── spotify_playlist_tracks_uri.sh
│   ├── spotify_playlist_tracks_uri_artist_track.sh
│   ├── spotify_playlist_tracks_uri_batch_by_year.sh
│   ├── spotify_playlist_tracks_uri_by_year.sh
│   ├── spotify_playlist_tracks_uri_in_year.sh
│   ├── spotify_playlist_uri_offset.sh
│   ├── spotify_playlists.sh
│   ├── spotify_playlists_json.sh
│   ├── spotify_release_year.sh
│   ├── spotify_rename_playlist.sh
│   ├── spotify_search.sh
│   ├── spotify_search_alternate_track_uris.sh
│   ├── spotify_search_json.sh
│   ├── spotify_search_uri.sh
│   ├── spotify_set_playlists_private.sh
│   ├── spotify_set_playlists_public.sh
│   ├── spotify_set_tracks_uri_to_liked.sh
│   ├── spotify_top_artists.sh
│   ├── spotify_top_artists_uri.sh
│   ├── spotify_top_tracks.sh
│   ├── spotify_top_tracks_uri.sh
│   ├── spotify_uri_json.sh
│   └── spotify_uri_to_name.sh
├── teamcity/
│   ├── .teamcity.vcs.json
│   ├── .teamcity.vcs.oauth.json
│   ├── .teamcity.vcs.ssh.json
│   ├── teamcity.sh
│   ├── teamcity_agents.sh
│   ├── teamcity_api.sh
│   ├── teamcity_builds.sh
│   ├── teamcity_buildtype_create.sh
│   ├── teamcity_buildtype_set_description_from_github.sh
│   ├── teamcity_buildtypes.sh
│   ├── teamcity_buildtypes_set_description_from_github.sh
│   ├── teamcity_create_github_oauth_connection.sh
│   ├── teamcity_create_project.sh
│   ├── teamcity_create_vcs_root.sh
│   ├── teamcity_export.sh
│   ├── teamcity_export_buildtypes.sh
│   ├── teamcity_export_project_config.sh
│   ├── teamcity_export_vcs_roots.sh
│   ├── teamcity_project_set_versioned_settings.sh
│   ├── teamcity_project_vcs_versioning.sh
│   ├── teamcity_projects.sh
│   ├── teamcity_upload_ssh_key.sh
│   └── teamcity_vcs_roots.sh
├── terraform/
│   ├── terraform_cloud_api.sh
│   ├── terraform_cloud_ip_ranges.sh
│   ├── terraform_cloud_organizations.sh
│   ├── terraform_cloud_varset_delete_vars.sh
│   ├── terraform_cloud_varset_set_vars.sh
│   ├── terraform_cloud_varset_vars.sh
│   ├── terraform_cloud_varsets.sh
│   ├── terraform_cloud_workspace_delete_vars.sh
│   ├── terraform_cloud_workspace_set_vars.sh
│   ├── terraform_cloud_workspace_vars.sh
│   ├── terraform_cloud_workspaces.sh
│   ├── terraform_gcs_backend_version.sh
│   ├── terraform_gitlab_download_backend_variable.sh
│   ├── terraform_import.sh
│   ├── terraform_import_aws_iam_groups.sh
│   ├── terraform_import_aws_iam_policies.sh
│   ├── terraform_import_aws_iam_users.sh
│   ├── terraform_import_aws_sso_account_assignments.sh
│   ├── terraform_import_aws_sso_managed_policy_attachments.sh
│   ├── terraform_import_aws_sso_permission_set_inline_policies.sh
│   ├── terraform_import_aws_sso_permission_sets.sh
│   ├── terraform_import_foreach.sh
│   ├── terraform_import_github_repos.sh
│   ├── terraform_import_github_team.sh
│   ├── terraform_import_github_team_repos.sh
│   ├── terraform_import_github_teams.sh
│   ├── terraform_managed_resource_types.sh
│   ├── terraform_provider_count_sizes.sh
│   ├── terraform_registry_url_extract.sh
│   ├── terraform_registry_url_open.sh
│   ├── terraform_registry_url_to_https.sh
│   └── terraform_resources.sh
├── tests/
│   ├── README.md
│   ├── azure_devops_url_conversion.sh
│   └── test_spotify_uri_to_name.sh
├── travis/
│   ├── .travis.yml
│   ├── travis_api.sh
│   ├── travis_delete_cron.sh
│   ├── travis_foreach_repo.sh
│   ├── travis_lint.sh
│   ├── travis_repo_build.sh
│   ├── travis_repo_caches.sh
│   ├── travis_repo_create_cron.sh
│   ├── travis_repo_crons.sh
│   ├── travis_repo_delete_caches.sh
│   ├── travis_repo_delete_crons.sh
│   ├── travis_repo_env_vars.sh
│   ├── travis_repo_settings.sh
│   ├── travis_repos.sh
│   ├── travis_repos_caches.sh
│   ├── travis_repos_create_cron.sh
│   ├── travis_repos_crons.sh
│   ├── travis_repos_delete_caches.sh
│   ├── travis_repos_delete_crons.sh
│   └── travis_repos_settings.sh
├── vagrant/
│   ├── vagrant_hosts.sh
│   └── vagrant_total_mb.sh
├── wercker/
│   ├── .werckerignore
│   ├── wercker.yml
│   ├── wercker_api_app.sh
│   ├── wercker_api_runs.sh
│   ├── wercker_api_workflows.sh
│   └── wercker_app_id.sh
└── yamllint/
    └── config

================================================
FILE CONTENTS
================================================

================================================
FILE: .appveyor.yml
================================================
#
#  Author: Hari Sekhon
#  Date: 2020-02-24 16:19:35 +0000 (Mon, 24 Feb 2020)
#
#  vim:ts=2:sts=2:sw=2:et
#
#  https://github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

# ============================================================================ #
#                             A p p V e y o r   C I
# ============================================================================ #

# https://www.appveyor.com/docs/appveyor-yml/

image: Ubuntu

# workaround for default JDK9 have old CA certs:
#
#   https://github.com/appveyor/ci/issues/3833
#
#   https://www.appveyor.com/docs/getting-started-with-appveyor-for-linux/#configuring-language-stack
#
stack: jdk 15

skip_commits:
  files:
    - docs/*
    - '**/*.md'

# https://www.appveyor.com/docs/how-to/ssh-to-build-worker/
environment:
  APPVEYOR_SSH_KEY: ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAvihSRU+YjBKvKiacDfUoZ7ghoVMcwNh4cWIYUNFGZosXOzNtyOcBpIb71TCgLFhOd+aMWKXCEC67BpNSIjt+a/FLD27AwmgVHv6cPlE3G0JJ9zmIrNmx9511dshTsxUW2O0SbYG+3InuO7FUkSrld+kA1OucyjgmZU7/+Cs9shpAEOaIVYmGlpDGRucAHpwtckvdgRTtnA3WNZ/Qg1vU6Ik4Xm03vjrW6lSiuTffYO1kbdcMQ4IZBlzfmovOtXQ0PomvN5NMCpgOyQuoNlvyS11tOXoqNiWOkiLE15XEzAQth9hHbNiH8jHJbAtkHqWWh0KK4IUyNGvoL6QfNxsTlw== hari@anotherdimension

# enable SSH session accessible via my public key
#init:
#  - sh: curl -sflL 'https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-ssh.sh' | bash -e -

# more useful at end to leverage .appveyor.yml tweaks like disabling broken mssql repo/dependencies, checking out project and building the core stuff happen first so we don't have to do all that manually in SSH session
on_finish:
  # set this in Settings -> Environment dynamically instead of here
  #- sh: export APPVEYOR_SSH_BLOCK=true
  #
  # workaround for https://github.com/appveyor/ci/issues/3373
  #            and https://github.com/appveyor/ci/issues/3384
  #
  # has since been added to AppVeyor's own scripts:
  #
  #     https://github.com/appveyor/ci/pull/3385
  #
  #- sh: curl -sflL 'https://raw.githubusercontent.com/HariSekhon/DevOps-Bash-tools/master/install/install_openssh.sh' | bash -e -
  #
  # https://www.appveyor.com/docs/how-to/ssh-to-build-worker/
  - sh: if [ "$APPVEYOR_SSH_BLOCK" = true ]; then curl -sflL 'https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-ssh.sh' | bash -e -; fi

install:
  # workaround for:
  # Some packages could not be installed. This may mean that you have
  # requested an impossible situation or if you are using the unstable
  # distribution that some required packages have not yet been created
  # or been moved out of Incoming.
  # The following information may help to resolve the situation:
  #
  # The following packages have unmet dependencies:
  #  mssql-server : Depends: libsasl2-modules-gssapi-mit but it is not going to be installed
  #  E: Error, pkgProblemResolver::Resolve generated breaks, this may be caused by held packages.
  #  bash-tools/Makefile.in:272: recipe for target 'apt-packages' failed
  #  make[2]: *** [apt-packages] Error 123
  #  make[2]: Leaving directory '/home/appveyor/projects/pylib'
  #  bash-tools/Makefile.in:212: recipe for target 'system-packages' failed
  #
  #  adding "|| :" to the end of these commands causes them to be silently ignored!
  - sudo sed -i '/https:\/\/packages.microsoft.com\/ubuntu\/.*\/mssql-server/d' /etc/apt/sources.list
  - sudo apt purge -yq --allow-change-held-packages mssql-server
  # this prevents conflicts installing default-jdk - see https://github.com/appveyor/ci/issues/3411
  #- dpkg -l | awk '/openjdk/{print $2}' | DEBIAN_FRONTEND=noninteractive xargs sudo apt-get remove -y --allow-change-held-packages
  - setup/ci_bootstrap.sh
  - make

test_script:
  - make test

build: off


================================================
FILE: .bash.d/Makefile
================================================
#
#  Author: Hari Sekhon
#  Date: 2016-01-17 12:56:53 +0000 (Sun, 17 Jan 2016)
#
#  vim:ts=4:sts=4:sw=4:noet
#
#  https://github.com/HariSekhon/DevOps-Bash-tools
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback
#
#  https://www.linkedin.com/in/HariSekhon
#

include ../Makefile.in

REPO := HariSekhon/DevOps-Bash-tools

BASH_TOOLS := ..

.PHONY: readme
readme:
	@source $(BASH_TOOLS)/.bash.d/network.sh; browser "https://github.com/$(REPO)/blob/master/.bash.d/README.md"


================================================
FILE: .bash.d/README.md
================================================
Advanced Bashrc Code - Interactive Functions, Aliases and Shell Customizations
==============================================================

Advanced bashrc code I've been using for ~15 years, I've ported nearly 5000 lines to this public repo so far.

All `*.sh` files in this directory are automatically sourced by `.bashrc` at the top level which is itself designed to be sourced in your `$HOME/.bashrc`.

To disable any these source files, simply rename them to not match the `*.sh` glob, eg. => `*.sh.disabled`.

- `aliases.sh` - general aliases
- `functions.sh` - general functions eg. `pass` which prompts for a password which is saved to an environment variable and auto-populated in various top-level API querying scripts built on `curl_auth.sh`
- `env.sh` - general environment variables and var/unvar functions for setting environment variables for the current and all new shell sessions
- `paths.sh` - deduplicated adding to `$PATH` for lots of common places (eg. /usr/sbin, /usr/local/bin, ~/bin) and commands to clearly print one path per line for Bash `$PATH`, Perl `@INC` and Python `sys.path`. Also contains technology specific paths when there is no `<technology>.sh` file. All other includes use `add_PATH()` function defined here.
- `<technology>.sh` - aliases, functions and environment variables to make interactive day-to-day use of a specific technologies easier
  - Cloud / Containerization / Virtualization:
    - `aws.sh` - [AWS](https://aws.amazon.com) functions:
      - `aws_env` - populates credentials from `~/.aws/credentials` / `~/.boto` section given as an argument to `$AWS_ACCESS_KEY` and `$AWS_SECRET_KEY` environment variables and sets `$AWS_PROFILE` to the profile name (defaults to the 'default' profile and creds if no argument is specified)
      - `aws_envs` - prints the available envs configured in the aws credentials file and stars the one currently in use
      - `awk_token` - generates a 24-hour MFA session token, exports it as `$AWS_SESSION_TOKEN` for use with [AWS CLI](https://aws.amazon.com/cli/), and saves it to `~/.aws/token` for loading to other shells that call `aws_env`
    - `docker.sh` - [Docker](https://www.docker.com/) convenient aliases and functions like clearing old containers and dangling image layers to clean up space
    - `kubernetes.sh` - [Kubernetes](https://kubernetes.io/) aliases and functions, managing contexts and namespaces even for periodically regenerated `.kube/config` with refreshed embedded certificates, switching between open source [Kubernetes](https://kubernetes.io/) and Redhat [OpenShift](https://www.openshift.com/) `kubectl` and `oc` commands, automating getting authentication token and Kubernetes API endpoints
    - `vagrant.sh` - [Vagrant](https://www.vagrantup.com/) aliases and functions
  - Automation / Distributed Systems:
    - `ansible.sh` - [Ansible](https://www.ansible.com) aliases and environment variables
    - `kafka.sh` - [Kafka](http://kafka.apache.org/) environment variables for Kerberos security and CLI appropriate heap size (avoids heap allocation failures on VMs that otherwise default to using larger server configured heap size), avoiding need for common broker and zookeeper arguments when using `kafka_wrappers/` scripts by setting your Kafka broker and zookeeper addresses once instead of in every command
  - Coding:
    - `git.sh` - [Git](https://git-scm.com/) aliases and functions
    - `mercurial.sh` - [Mercurial](https://www.mercurial-scm.org/) aliases and functions
    - `svn.sh` - [Svn](https://subversion.apache.org) aliases and functions
    - `java.sh` - [Java](https://www.java.com/en/) detection and setting of `$JAVA_HOME` for Linux and Mac environments
  - OS:
    - `apple.sh` - [Apple Mac OS X / macOS](https://en.wikipedia.org/wiki/MacOS) specific tricks
    - `linux.sh` - [Linux](https://en.wikipedia.org/wiki/Linux) specific miscellaneous bits like X.org
    - `network.sh` - network aliases and functions
    - `ssh.sh` - SSH convenience functions and key management
    - `ssh-agent.sh` / `gpg-agent.sh` - auto-starts SSH and GPG agents if not already running, stores and auto-sources their details for new shells to automatically use them
    - `title.sh` - auto-title tricks for Screen and Terminals

More script related functions can be found in the [lib/](https://github.com/HariSekhon/DevOps-Bash-tools/tree/master/lib) directory at the top level.


================================================
FILE: .bash.d/aliases.sh
================================================
#!/usr/bin/env bash
# shellcheck disable=SC2230,SC2139
#  vim:ts=4:sts=4:sw=4:et
#
#  Author: Hari Sekhon
#  Date: circa 2006 (forked from .bashrc)
#
#  https://github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

# ============================================================================ #
#                         G e n e r a l   A l i a s e s
# ============================================================================ #

bash_tools="${bash_tools:-$(dirname "${BASH_SOURCE[0]}")/..}"

# shellcheck disable=SC1090,SC1091
. "$bash_tools/.bash.d/os_detection.sh"

# shellcheck disable=SC1090,SC1091
#. "$bash_tools/.bash.d/paths.sh"

# manual local aliases
# shellcheck disable=SC1090,SC1091
[ -f ~/.aliases ] && . ~/.aliases

# bash_tools defined in .bashrc
# shellcheck disable=SC2154
export bashrc=~/.bashrc
export bashrc2="$bash_tools/.bashrc"
alias reload='. $bashrc'
alias r='reload'
alias rq='set +x; . $bashrc; set -x'
alias bashrc='$EDITOR $bashrc && reload'
alias bashrc2='$EDITOR $bashrc2 && reload'
alias bashrclocal='$EDITOR $bashrc.local; reload'
alias bashrc3=bashrclocal
alias v='vim'
alias vimrc='$EDITOR ~/.vimrc'
alias screenrc='$EDITOR ~/.screenrc'
alias aliases='$EDITOR $bashd/aliases.sh'
alias ae=aliases
alias be=bashrc
alias be2=bashrc2
alias be3=bashrc3
alias se=screenrc
alias ve=vimrc
alias creds='$EDITOR ~/.env/creds'
alias pbc=pbcopy
alias pbp=pbpaste
# keep emacs with no window, use terminal, not X, otherwise I'd run xemacs...
#alias emacs="emacs -nw"
#em(){ emacs "$@" ; }
#alias em=emacs
#alias e=em
#xe(){ xemacs $@ & }
#alias x=xe

# from DevOps-Perl-tools repo which must be in $PATH
# done via functions.sh now
#alias new=new.pl

# not present on Mac
#type tailf &>/dev/null || alias tailf="tail -f"
alias tailf="tail -f"  # tail -f is better than tailf anyway
alias mv='mv -i'
alias cp='cp -i'
#alias rm='rm -i'
# allows to re-use custommized less behaviour throughout profile without duplicating options
#less='less -RFXig'
#alias less='$less'
export LESS="-RFXig --tabs=4"
# will require LESS="-R"
if type -P pygmentize &>/dev/null; then
    # shellcheck disable=SC2016
    export LESSOPEN='| "$bash_tools/python/pygmentize.sh" "%s"'
fi
alias l='less'
alias m='more'
alias vi='vim'
# used by vagrant now
#alias v='vim'
alias grep='grep --color=auto'
# in functions.sh for multiple args now
#alias envg="env | grep -i"
alias dec="decomment.sh"

alias dns='cat /etc/resolv.conf'
alias hosts='sudo $EDITOR /etc/hosts'
alias repos='$EDITOR $bash_tools/setup/repos.txt'

alias path="echo \$PATH | tr ':' '\\n' | less"
alias paths=path

alias tmp="cd /tmp"

alias mksupportdir="mkdir -v support-bundle-$(date '+%F_%H%M')"

# not as compatible, better to call pypy explicitly or in #! line
#if type -P pypy &>/dev/null; then
#    alias python=pypy
#fi

# shellcheck disable=SC2139
bt="$(dirname "${BASH_SOURCE[0]}")/.."
export bt
alias bt='sti bt; cd $bt'

# shellcheck disable=SC2154
export bashd="$bash_tools/.bash.d"
alias bashd='sti bashd; cd $bashd'

#alias cleanshell='env - bash --rcfile /dev/null'
alias cleanshell='env - bash --norc --noprofile'
alias newshell='exec bash'
alias rr='newshell'

alias record=script

alias dl="BACKGROUND_VIDEO=1 youtube_download_video.sh"
#alias vidopen="vidopen.sh"
#alias vidopenplay="PLAY_VIDEO=1 vidopen.sh"

alias l33tmode='welcome; retmode=on; echo l33tm0de on'
alias leetmode=l33tmode

alias hist=history
alias clhist='HISTSIZE=0; HISTSIZE=5000'
alias nohist='unset HISTFILE'
alias histgrep='history | grep'

export LS_OPTIONS='-F'
if is_mac; then
    export CLICOLOR=1 # equiv to using -G switch when calling
else
    export LS_OPTIONS="$LS_OPTIONS --color=auto"
    export PS_OPTIONS="$LS_OPTIONS -L"
fi

alias ls='ls $LS_OPTIONS'
# omit . and .. in listall with -A instead of -a
alias lA='ls -lA $LS_OPTIONS'
alias la='ls -la $LS_OPTIONS'
alias ll='ls -l $LS_OPTIONS'
alias lh='ls -lh $LS_OPTIONS'
alias lr='ls -ltrh $LS_OPTIONS'
alias ltr='lr'
alias lR='ls -lRh $LS_OPTIONS'

# shellcheck disable=SC2086
lw(){ ls -lh $LS_OPTIONS "$(type -P "$@")"; }

# shellcheck disable=SC2086,SC2012
lll(){ ls -l "$(readlink -f "${@:-.}")" | less -R; }

alias cd..='cd ..'
alias ..='cd ..'
alias ...='cd ../..'
alias ....='cd ../../..'
#up(){
#    local times="${1:-1}"
#    if ! [[ "$times" =~ ^[[:digit:]]$ ]]; then
#        echo "How many directories to go up"
#        echo
#        echo "usage: up <num>"
#        return 1
#    fi
#    while [ "$times" -gt 0 ]; do
#        cd ..
#        times=$((times - 1))
#    done
#}
# use bare 'cd' instead, it's more standard
#alias ~='cd ~'

alias screen='screen -T $TERM'
#alias mt=multitail
#alias halt='shutdown -h now -P'
# my pytools github repo
alias ht='headtail.py'

alias run='run.sh'

# ============================================================================ #
#           GitHub / GitLab / BitBucket / Azure DevOps repo checkouts
# ============================================================================ #

export github=~/github
export gitlab=~/gitlab
export azure_devops=~/azure-devops
alias github="sti github; cd '$github'";
export work="$github/work"
alias work="sti work; cd '$work'"

alias btup="bt; u; cd -"

export bitbucket=~/bitbucket
alias bitb='cd $bitbucket'
# clashes with bitbucket-cli
#alias bitbucket='cd $bitbucket'
# used to gitbrowse to bitbucket now in git.sh
#alias bb=bitbucket

alias diag=diagrams

aliasdir(){
    local directory="$1"
    local suffix="${2:-}"
    [ -d "$directory" ] || return 0
    name="${directory##*/}"
    name="${name//-/_}"
    name="${name//./_}"
    name="${name// /}"
    # alias terraform /tf -> terra
    if [[ "$name" =~ ^(terraform|tf)$ ]]; then
        name="terra"
    fi
    if [ -z "${!name:-}" ]; then
        export "$name"="$directory"
    fi
    # don't clash with any binaries
    #if ! type -P "${name}${suffix}" &>/dev/null; then
    # don't clash with binaries or any previous defined aliases or functions
    if ! type "${name}${suffix}" &>/dev/null; then
        # shellcheck disable=SC2139,SC2140
        alias "${name}${suffix}"="sti $name; cd $directory"
    elif ! type "g${name}${suffix}" &>/dev/null; then
        # shellcheck disable=SC2139,SC2140
        alias "g${name}${suffix}"="sti $name; cd $directory"
    fi
}

for basedir in "$github" "$gitlab" "$bitbucket" "$azure_devops"; do
    if [ -d "$basedir" ]; then
        for directory in "$basedir/"*; do
            aliasdir "$directory"
            if [[ "$directory" =~ /work$ ]]; then
                for workdir in "$directory/"*; do
                    aliasdir "$workdir" "w"  # work dirs should have a w suffix
                done
            fi
        done
    fi
done


doc_alias(){
    local docpath="$1"
    local prefix="${2:-d}"
    [ -f "$docpath" ] || return 1
    docfile="${docpath##*/}"
    if ! [[ "$docfile" =~ \.(txt|md)$ ]]; then
        if [[ "$docfile" =~ \. ]]; then
            return 1
        fi
    fi
    # slows down shell creation, will drain battery
#    if [ -L "$docpath" ]; then
#        # brew install coreutils to get greadlink since Mac doesn't have readlink -f
#        if type -P greadlink &>/dev/null; then
#            docfile="$(greadlink -f "$docpath")"
#        else
#            docfile="$(readlink -f "$docpath")"
#        fi
#    fi
    #local count=0
    #[ -f ~/docs/$docfile ] && ((count+=1))
    #[ -f "$github/docs/$docfile" ] && ((count+=1))
    #[ -f "$bitbucket/docs/$docfile" ] && ((count+=1))
    #if [ $count -gt 1 ]; then
    #    echo "WARNING: $docfile conflicts with existing alias, duplicate doc '$docfile' among ~/docs, ~/github/docs, ~/bitbucket/docs?"
    #    return
    #fi
    local shortname="${docfile%.md}"
    local shortname="${shortname%.txt}"
    # shellcheck disable=SC2139,SC2140
    alias "${prefix}${shortname}"="ti ${docpath##*/}; \$EDITOR $docpath"
}

for x in ~/docs/* "$github"/docs/* "$bitbucket"/docs/*; do
    doc_alias "$x" || :
done

alias know="knowledge"
for x in ~/knowledge/* "$github"/knowledge/* "$bitbucket"/knowledge/*; do
    doc_alias "$x" k || :
done

# ============================================================================ #

# set in ansible.sh
#alias a='ansible -Db'
alias anonymize='anonymize.py'
alias an='anonymize -a'
alias bc='bc -l'
alias chromekill='pkill -f "Google Chrome Helper"'
alias eclipse='~/eclipse/Eclipse.app/Contents/MacOS/eclipse';
alias visualvm='~/visualvm/bin/visualvm'

alias tmpl=templates

# using brew version on Mac
pmd_opts="-R rulesets/java/quickstart.xml -f text"
if is_mac; then
    # yes evaluate $pmd_opts here
    # shellcheck disable=SC2139
    pmd="pmd $pmd_opts"
else
    for x in ~/pmd-bin-*; do
        if [ -f "$x/bin/run.sh" ]; then
            # yes evaluate $x here, and don't export it's lazy evaluated in alias below
            # shellcheck disable=SC2139,SC2034
            pmd="$x/bin/run.sh pmd $pmd_opts"
        fi
    done
fi
alias pmd='$pmd'

# from DevOps Perl tools repo - like uniq but doesn't require pre-sorting keeps the original ordering
# Devops Golang tools uniq2 should be on path instead now
#alias uniq2=uniq_order_preserved.pl

# for piping from grep
alias uniqfiles="sed 's/:.*//;/^[[:space:]]*$/d' | sort -u"

export etc=~/etc
alias etc='cd $etc'


alias distro='cat /etc/*release /etc/*version 2>/dev/null'
alias trace=traceroute
alias t='$EDITOR ~/temp-notes.txt'
# causes more problems than it solves on a slow machine missing the prompt
#alias y=yes
alias t2='$EDITOR ~/tmp2'
alias t3='$EDITOR ~/tmp3'
#alias tg='traceroute www.google.com'
#alias sec='ps -ef| grep -e arpwatc[h] -e swatc[h] -e scanlog[d]'


export lab=~/lab
alias lab='cd $lab'

# Auto-alias uppercase directories in ~ like Desktop and Downloads
#for dir in $(find ~ -maxdepth 1 -name '[A-Z]*' -type d); do [ -d "$dir" ] && alias ${dir##*/}="cd '$dir'"; done

export Downloads=~/Downloads
export Documents=~/Documents
alias Downloads='cd "$Downloads"'
alias Documents='cd "$Documents"'
export down="$Downloads"
export docu="$Documents"
alias down='cd "$Downloads"'
alias docu='cd "$Documents"'
alias doc='cd ~/docs'

export desktop=~/Desktop
export desk="$desktop"
alias desktop='cd "$desktop"'
alias desk=desktop

export screenshots=~/Desktops/Screenshots
alias screenshots='cd "$screenshots"'

export bin=~/bin
alias bin="cd $bin"

alias todo='ti T; $EDITOR ~/TODO'
alias TODO="todo"
alias don='ti D; $EDITOR ~/DONE'
alias DON=don

# drive => Google Drive
export google_drive=~/drive
export drive="$google_drive"
alias drive='cd "$drive"'

for v in ~/github/pytools/validate_*.py; do
    z="${v##*/}"
    z="${z#validate_}"
    z="${z%.py}"
    # needs to expand now for dynamic alias creation
    # shellcheck disable=SC2139,SC2140
    alias "v$z"="$v"
done

# in some environments I do ldap with Kerberos auth - see ldapsearch.sh script at top level which is more flexible with pre-tuned environment variables
#alias ldapsearch="ldapsearch -xW"
#alias ldapadd="ldapadd -xW"
#alias ldapmodify="ldapmodify -xW"
#alias ldapdelete="ldapdelete -xW"
#alias ldappasswd="ldappasswd -xW"
#alias ldapwhoami="ldapwhoami -xW"
#alias ldapvi="ldapvi -b dc=domain,dc=local -D cn=admin,dc=domain,dc=local"

alias fluxkeys='$EDITOR ~/.fluxbox/keys'
alias fke=fluxkeys
alias fluxmenu='$EDITOR ~/.fluxbox/mymenu'
alias fme=fluxmenu
alias mymenu=fluxmenu
alias menu=mymenu

# trigger script in ~/.config/mpv/scripts/delete-on-eof.lua to delete a video once it has been completely watched
alias mpvd="MPV_DELETE_ON_EOF=1 mpv --speed=2"


================================================
FILE: .bash.d/android.sh
================================================
#!/usr/bin/env bash
#  vim:ts=4:sts=4:sw=4:et
#
#  Author: Hari Sekhon
#  Date: 2025-02-27 02:08:34 +0700 (Thu, 27 Feb 2025)
#
#  https///github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

export ANDROID_HOME="$HOME/Android/Sdk"

# Doesn't work
#export ANDROID_SDK_ROOT="$ANDROID_HOME"

add_PATH "$ANDROID_HOME/platform-tools"

add_PATH "$ANDROID_HOME/cmdline-tools/latest/bin"
add_PATH "$ANDROID_HOME/cmdline-tools/bin"

for x in "$ANDROID_HOME/build-tools/"*; do
    if [ -d "$x" ]; then
        add_PATH "$x"
    fi
done


================================================
FILE: .bash.d/ansible.sh
================================================
#!/usr/bin/env bash
#  vim:ts=4:sts=4:sw=4:et
#  shellcheck disable=SC2139
#
#  Author: Hari Sekhon
#  Date: 2014-07-13 16:56:14 +0100
#
#  https://github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

# ============================================================================ #
#                                 A n s i b l e
# ============================================================================ #

bash_tools="${bash_tools:-$(dirname "${BASH_SOURCE[0]}")/..}"

# shellcheck disable=SC1090,SC1091
#type add_PATH &>/dev/null || . "$bash_tools/.bash.d/paths.sh"

# order of precedence:
#
#   $ANSIBLE_CONFIG
#   $PWD/ansible.cfg
#   $HOME/.ansible.cfg
#   /etc/ansible/ansible.cfg
#
# so don't set ANSIBLE_CONFIG because it'll cause issues in work repos
# which would otherwise correctly default to $PWD/ansible.cfg
#
#export ANSIBLE_CONFIG=~/.ansible.cfg  # symlinked to $bash_tools/configs/.ansible.cfg

if [ -n "${ANSIBLE_HOME:-}" ]; then
    add_PATH PYTHONPATH "$ANSIBLE_HOME/lib"
    add_PATH ANSIBLE_LIBRARY "$ANSIBLE_HOME/library"
    # resets man search path, breaking man lookups
    #add_PATH MANPATH "$ANSIBLE_HOME/docs/man"
fi

# don't set this in case it causes issues in work repos
#if [ -f ~/etc/ansible/hosts ]; then
#    export ANSIBLE_HOSTS=~/etc/ansible/hosts
#fi

# set in ~/.ansible.cfg now
#export ANSIBLE_HOST_KEY_CHECKING=False

# -D diff switch requires newish ansible, doesn't work on 1.7
# -b - matter of preference between using lots of sudo in manifests or not, better to remove it for tighter authz & logging purposes in governed environments
ansible_opts="-D -b"

alias a=ansible
# expand now, no dynamic surprises
alias ansible="ansible $ansible_opts"
alias ansible_playbook="ansible-playbook $ansible_opts"
#alias ansible_playbook_vault="ansible-playbook $ansible_opts --ask-vault-pass"
alias ansible_playbook_vault="ansible-playbook $ansible_opts --vault-id '$bash_tools/bin/vault_pass.sh'"


================================================
FILE: .bash.d/argocd.sh
================================================
#!/usr/bin/env bash
#  vim:ts=4:sts=4:sw=4:et
#
#  Author: Hari Sekhon
#  Date: 2022-01-07 16:03:39 +0000 (Fri, 07 Jan 2022)
#
#  https://github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help improve or steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

# ============================================================================ #
#                                  A r g o C D
# ============================================================================ #

# gets default admin pw and copies it to clipboard for quick pasting to UI
alias argopass="argocd_password.sh | copy_to_clipboard.sh"

# XXX: set the following in your local environment:
#
# ARGOCD_SERVER=localhost:8080  # without the http:// or https:// prefix
# ARGOCD_AUTH_TOKEN='<token>'

if ! [[ "${ARGOCD_OPTS:-}" =~ --grpc-web ]]; then
    export ARGOCD_OPTS="$ARGOCD_OPTS --grpc-web"
fi
#export ARGOCD_OPTS="--grpc-web --insecure"  # only in local dev

argosync(){
    local seconds="${1:-60}"
    shift || :
    if [ -z "${ARGOCD_APP:-}" ]; then
        namespace="${K8S_NAMESPACE:-$(kubectl_namespace)}"
        if argocd app list -o name | grep -Fxq "$namespace"; then
            ARGOCD_APP="$namespace"
        fi
    fi
    if [ -n "${ARGOCD_APP:-}" ]; then
        timestamp "ArgoCD Syncing App '$ARGOCD_APP'"
        echo
        argocd app sync "$ARGOCD_APP" --force "$@"
        argocd app wait "$ARGOCD_APP" --timeout "$seconds" "$@"
        echo
        if [ "$ARGOCD_APP" = argocd ]; then
            for x in projects apps; do
                if argocd app list -o name | grep -Fxq "$x"; then
                    ARGOCD_APP="$x" argosync "$@"
                fi
            done
        fi
    else
        echo "\$ARGOCD_APP is not set" >&2
        return 1
    fi
}


================================================
FILE: .bash.d/aws-cloudshell.sh
================================================
#!/usr/bin/env bash
#  vim:ts=4:sts=4:sw=4:et
#
#  Author: Hari Sekhon
#  Date: 2020-12-17 18:54:23 +0000 (Thu, 17 Dec 2020)
#
#  https://github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

# This is designed to mimick the standard GCP CloudShell behaviour
# of re-customizing a new CloudShell

if ! [ "${AWS_EXECUTION_ENV:-}" = "CloudShell" ]; then
    return
fi

customize_script=~/.aws_customize_environment

lockdir=/tmp/aws_customize_environment.lock

completion_semaphore="/.aws_customize_environment_completed"

if ! [ -f "$customize_script" ]; then
    return
fi

if [ -f "$completion_semaphore" ]; then
    return
fi

# XXX: if the lockdir is more than 2 hours old and the completion semaphore wasn't found, remove the lockdir to try again
if [ -d "$lockdir" ] && ! [ -f "$completion_semaphore" ]; then
    lockdir_epoch="$(stat -c %Y "$lockdir")"
    current_epoch="$(date +%s)"
    if [ $((current_epoch - lockdir_epoch)) -gt 7200 ]; then
        rmdir "$lockdir"
    fi
fi

# used as a mutex lock
mkdir "$lockdir" 2>/dev/null || return

sudo bash <<EOF
    {

        date
        echo

        bash "$customize_script" &&

        rmdir "$lockdir" &&

        sudo UMASK=0044 touch "$completion_semaphore" &

    } > /var/log/customize_environment 2>&1
EOF


================================================
FILE: .bash.d/aws.sh
================================================
#!/usr/bin/env bash
#  vim:ts=4:sts=4:sw=4:et
#
#  Author: Hari Sekhon
#  Date: 2012-09-01 13:01:11 +0100
#
#  https://github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

# ============================================================================ #
#                A W S  -  A m a z o n   W e b   S e r v i c e s
# ============================================================================ #

bash_tools="${bash_tools:-$(dirname "${BASH_SOURCE[0]}")/..}"

# shellcheck disable=SC1090,SC1091
type add_PATH &>/dev/null || . "$bash_tools/.bash.d/paths.sh"
# shellcheck disable=SC1090,SC1091
#type autocomplete &>/dev/null || . "$bash_tools/.bash.d/functions.sh"

# ==================
# AWS CLI completion

aws_completer="$(type -P aws_completer 2>/dev/null)"

if [ -n "$aws_completer" ]; then
    complete -C "$aws_completer" aws
fi

#autocomplete eksctl

# =====================
# Elastic Beanstalk CLI (easier to use than AWS CLI)

if [ -d ~/.ebcli-virtual-env/executables/ ]; then
    add_PATH ~/.ebcli-virtual-env/executables/
fi

# ============================================================================ #
#                   A l i a s e s   a n d   F u n c t i o n s
# ============================================================================ #

alias awsl='aws sso login'

#alias s3='s3cmd'
alias s3='aws s3'
alias dockerecr='aws ecr get-login-password | docker login -u AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com'

alias awscon='aws_consoler -o'
alias awsc='awscon'

alias aws_whoami="aws sts get-caller-identity"
alias awhoami=aws_whoami

# loads creds from a CLI cache file (eg. for AWS SSO) into environment variables
# better done via direnv
awscreds(){
    # should be something like ~/.aws/cli/cached/[hash].json
    local cred_cache_file="$1"
    AWS_ACCESS_KEY_ID="$(jq -r .Credentials.AccessKeyId < "$cred_cache_file")"
    AWS_SECRET_ACCESS_KEY="$(jq -r .Credentials.SecretAccessKey < "$cred_cache_file")"
    AWS_SESSION_TOKEN="$(jq -r .Credentials.SessionToken < "$cred_cache_file")"
    export AWS_ACCESS_KEY_ID
    export AWS_SECRET_ACCESS_KEY
    export AWS_SESSION_TOKEN
}

# ==================
# AWLess completion

alias awl=awless
alias assh="awless ssh"

#autocomplete awless
# make completion work with awl alias above
#if ! [ -f ~/.bash.autocomplete.d/awl.sh ]; then
#    sed 's/awless/awl/g' ~/.bash.autocomplete.d/awless.sh > ~/.bash.autocomplete.d/awl.sh
#fi
#autocomplete awl

# ==================

# JAVA_HOME needs to be set to use EC2 api tools
#[ -x /usr/bin/java ] && export JAVA_HOME=/usr  # errors but still works

# Shouldn't be needed any more, all these sorts of tools were unified on awscli
#
# link_latest '/usr/local/ec2-api-tools-*'
#if [ -d /usr/local/ec2-api-tools/bin ]; then
#    export EC2_HOME=/usr/local/ec2-api-tools   # this should be a link to the unzipped ec2-api-tools-1.6.1.4/
#    add_PATH "$EC2_HOME/bin"
#fi

# ============================================================================ #

# Old: new direnv now
#
# ec2dre - ec2-describe-regions - list regions you have access to and put them here
# TODO: pull a more recent list and have aliases/functions auto-generated from that to export
#aws_eu(){
#    export EC2_URL=ec2.eu-west-1.amazonaws.com
#}
#aws_useast(){
#    export EC2_URL=ec2.us-east-1.amazonaws.com
#}
#aws_eu

# ============================================================================ #

# https://github.com/remind101/assume-role
assume-role(){
    #eval "$(command assume-role "$@")"
    local output
    output="$(command assume-role "$@")"
    # shellcheck disable=SC2181
    if [ $? -eq 0 ]; then
        eval "$output"
    fi
}

# ============================================================================ #

aws_get_cred_path(){
    # unreliable that HOME is set, ensure shell evaluates to the right thing before we use it
    [ -n "${HOME:-}" ] || HOME=~
    local aws_credentials="${AWS_SHARED_CREDENTIALS_FILE:-$HOME/.aws/credentials}"
    local aws_config="${AWS_CONFIG_FILE:-$HOME/.aws/config}"
    local boto="${BOTO_CONFIG:-$HOME/.boto}"
    local credentials_file
    if [ -f "$aws_credentials" ]; then
        credentials_file="$aws_credentials"
    # older boto creds
    elif [ -f "$boto" ]; then
        credentials_file="$boto"
    elif [ -f "$aws_config" ]; then
        credentials_file="$aws_config"
    else
        echo "no credentials found - didn't find $aws_credentials or $boto or $aws_config" 2>/dev/null
        return 1
    fi
    echo "$credentials_file"
}

# this rarely changes so just set it once as initialization instead of passing lots of params
# or re-executing aws_get_cred_path() multiple times in different functions
aws_credentials_file="$(aws_get_cred_path)"

aws_clean_env(){
    echo "clearing AWS_* environment variables"
    while read -r envvar; do
        unset "$envvar"
    done < <(env | sed -n '/^AWS_/ s/=.*// p')
}

# easily set a profile env var
#aws_profile(){
#    # false positive
#    # shellcheck disable=SC2317
#    export AWS_PROFILE="$*"
#}

alias awsprofile=aws_profile.sh
alias awsp=aws_profile.sh

aws_get_profile_data(){
    local profile="$1"
    local filename="${2:-$aws_credentials_file}"
    sed -n "/[[:space:]]*\\[\\(profile[[:space:]]*\\)*$profile\\]/,/^[[:space:]]*\\[/p" "$filename"
}

# Storing creds in one place in Boto creds file, pull them straight from there
# if only using new creds, might want to just export AWS_PROFILE instead using aws_profile which provides validation
aws_env(){
    local profile="${1:-default}"
    # export AWS_ACCESS_KEY
    # export AWS_SECRET_KEY
    # export AWS_SESSION_TOKEN - for multi-factor authentication
    local aws_token=~/.aws/token
    aws_profile "$profile" || return 1
    # section is checked for existence as part of aws_profile(), will return before here if not valid
    local profile_data
    profile_data="$(aws_get_profile_data "$profile")"
    echo "loading [$profile] creds from $aws_credentials_file"
    eval "$(
    for key in aws_access_key_id aws_secret_access_key aws_session_token; do
        awk -F= "/^[[:space:]]*$key/"'{gsub(/[[:space:]]+/, "", $0); gsub(/_id/, "", $1); gsub(/_secret_access/, "_secret", $1); print "export "toupper($1)"="$2}' <<< "$profile_data"
    done
    )"
    if [ -f "$aws_token" ]; then
        echo "sourcing $aws_token"
        # shellcheck disable=SC1090,SC1091
        source "$aws_token"
    fi
}
alias awsenv=aws_env

aws_envs(){
    awk '/^[[:space:]]*\[.+\]/{print $1}' < "$aws_credentials_file" |
    sed 's/\[//;s/\]//' |
    while read -r profile; do
        default=0
        if [ "$profile" = "$AWS_PROFILE" ]; then
            local default=1
        elif [ -z "$AWS_PROFILE" ] &&
             [ "$profile" = "default" ]; then
            local default=1
        fi
        if [ "$default" = 1 ]; then
            echo -n "* "
        else
            echo -n "  "
        fi
        echo -n "$profile"
        if [ "$default" = 1 ] &&
           ! env | grep -q '^AWS_SECRET_KEY='; then
            echo -n " (keys not loaded to env)"
        fi
        echo
    done
}
alias awsenvs=aws_envs

aws_unenv(){
    unset AWS_ACCESS_KEY
    unset AWS_SECRET_KEY
    unset AWS_SESSION_TOKEN
}
alias awsunenv=aws_unenv

aws_token(){
    local output
    local token
    if [ $# -eq 0 ]; then
        echo "usage: aws_token <token_from_mfa_device> [<other_options>]"
        return 1
    fi
    if [ -z "${AWS_MFA_ARN:-}" ]; then
        echo "environment variable \$AWS_MFA_ARN not set - you need to"
        echo
        echo "export AWS_MFA_ARN=arn:aws:iam::<123456789012>:mfa/<user>"
        echo
        echo "(you might want to put that in your ~/.bashrc.local or similar)"
        return 1
    fi
    #aws sts get-session-token --serial-number arn-of-the-mfa-device --token-code code-from-token
    set -x
    output="$(aws sts get-session-token --serial-number "$AWS_MFA_ARN" --duration-seconds "${AWS_STS_DURATION_SECS:-129600}" --token-code "$@")"
    result=$?
    set +x
    echo "$output"
    if [ $result -ne 0 ]; then
        return $result
    fi
    if type -P jq &>/dev/null; then
        token="$(jq -r '.Credentials.SessionToken' <<< "$output")"
    else
        token-"$(awk -F: '/SessionToken/{print $2}' | sed 's/"//')"
    fi
    export AWS_SESSION_TOKEN="$token"
    echo "exported AWS_SESSION_TOKEN"
    echo
    echo "export AWS_SESSION_TOKEN=$token" > ~/.aws/token
    echo "saved to ~/.aws/token for other shells to source via aws_env()"
    echo
    echo "you can now use AWS CLI normally"
}
alias awstoken=aws_token


================================================
FILE: .bash.d/azure.sh
================================================
#!/usr/bin/env bash
#  vim:ts=4:sts=4:sw=4:et
#  shellcheck disable=SC1090,SC1091
#
#  Author: Hari Sekhon
#  Date: 2020-03-06 16:36:42 +0000 (Fri, 06 Mar 2020)
#
#  https://github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

# ============================================================================ #
#                                   A z u r e
# ============================================================================ #

srcdir="${srcdir:-$(dirname "${BASH_SOURCE[0]}")/..}"

# shellcheck disable=SC1090,SC1091
#type add_PATH &>/dev/null || . "$srcdir/.bash.d/paths.sh"

# Azure CLI from script install, installs to $HOME/lib and $HOME/bin
if [ -f ~/lib/azure-cli/az.completion ]; then
    source ~/lib/azure-cli/az.completion
fi

# assh is an alias to awless ssh
azssh(){
    local ip
    ip="$(az vm show --name "$1" -d --query "[publicIps]" -o tsv)"
    ssh azureuser@"$ip"
}


================================================
FILE: .bash.d/bash_it.sh
================================================
#!/usr/bin/env bash
#  vim:ts=4:sts=4:sw=4:et
#
#  Author: Hari Sekhon
#  Date: 2020-02-26 15:21:46 +0000 (Wed, 26 Feb 2020)
#
#  https://github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

# ============================================================================ #
#                                 B a s h   I T
# ============================================================================ #

return

if ! [ -d ~/.bash_it ]; then
    git clone --depth=1 https://github.com/Bash-it/bash-it.git ~/.bash_it
fi

export BASH_IT=~/.bash_it

export BASH_IT_THEME='bobby'


================================================
FILE: .bash.d/circleci.sh
================================================
#!/usr/bin/env bash
#  vim:ts=4:sts=4:sw=4:et
#
#  Author: Hari Sekhon
#  Date: 2022-08-02 12:21:34 +0100 (Tue, 02 Aug 2022)
#
#  https://github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

# ============================================================================ #
#                                C i r c l e C I
# ============================================================================ #

bash_tools="${bash_tools:-$(dirname "${BASH_SOURCE[0]}")/..}"

if ! type github_owner_repo &>/dev/null; then
    # shellcheck disable=SC1090,SC1091
    . "$bash_tools/.bash.d/git.sh"
fi

circleci_debug(){
    circleci_project_set_env_vars.sh github/$(github_owner_repo) DEBUG=1
}

circleci_undebug(){
    circleci_project_delete_env_vars.sh github/$(github_owner_repo) DEBUG
}


================================================
FILE: .bash.d/colors.sh
================================================
#!/usr/bin/env bash
#  shellcheck disable=SC2034
#  vim:ts=4:sts=4:sw=4:et
#
#  Author: Hari Sekhon
#  Date: 2012-06-25 15:20:39 +0100
#
#  https://github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

# ============================================================================ #
#                        Terminal ANSI Escape Color Codes
# ============================================================================ #

# Show color codes - adapted from http://codesnippets.joyent.com/posts/show/1517 example 1
#
# see also colors.pl from DevOps-Perl-tools repo which is slightly better
colors(){
    local text="hari"

    echo -e '\n                  40m      41m      42m      43m      44m      45m      46m      47m';

    for FGs in '    m' '   1m' '  30m' '1;30m' '  31m' '1;31m' '  32m' \
               '1;32m' '  33m' '1;33m' '  34m' '1;34m' '  35m' '1;35m' \
               '  36m' '1;36m' '  37m' '1;37m'; do
        FG=${FGs// /}
        # shellcheck disable=SC1117
        echo -en " $FGs \033[$FG  $text  "
        for BG in 40m 41m 42m 43m 44m 45m 46m 47m; do
            # shellcheck disable=SC1117
            echo -en "$EINS \033[$FG\033[$BG  $text  \033[0m";
        done
        echo
    done
    echo
}

# ============================================================================ #

# For Gentoo stylish prompts
#
# Find or write a full colour output table like seen here:
# Daniel Robbins prompt magic tip on ibm developerworks
#
# from http://wiki.archlinux.org/index.php/Color_Bash_Prompt
#
# would set 'readonly' but causes reloads to output readonly variable errors
# replaced \e with \033 as it is more portable on Mac script includes for lib/utils.sh tick_msg()
txtblk='\033[0;30m'  # Black - Regular
txtred='\033[0;31m'  # Red
txtgrn='\033[0;32m'  # Green
txtylw='\033[0;33m'  # Yellow
txtblu='\033[0;34m'  # Blue
txtpur='\033[0;35m'  # Purple
txtcyn='\033[0;36m'  # Cyan
txtwht='\033[0;37m'  # White
bldblk='\033[1;30m'  # Black - Bold
bldred='\033[1;31m'  # Red
bldgrn='\033[1;32m'  # Green
bldylw='\033[1;33m'  # Yellow
bldblu='\033[1;34m'  # Blue
bldpur='\033[1;35m'  # Purple
bldcyn='\033[1;36m'  # Cyan
bldwht='\033[1;37m'  # White
unkblk='\033[4;30m'  # Black - Underline
undred='\033[4;31m'  # Red
undgrn='\033[4;32m'  # Green
undylw='\033[4;33m'  # Yellow
undblu='\033[4;34m'  # Blue
undpur='\033[4;35m'  # Purple
undcyn='\033[4;36m'  # Cyan
undwht='\033[4;37m'  # White
bakblk='\033[40m'    # Black - Background
bakred='\033[41m'    # Red
bakgrn='\033[42m'    # Green
bakylw='\033[43m'    # Yellow
bakblu='\033[44m'    # Blue
bakpur='\033[45m'    # Purple
bakcyn='\033[46m'    # Cyan
bakwht='\033[47m'    # White
txtrst='\033[0m'     # Text Reset


================================================
FILE: .bash.d/custom.sh
================================================
#!/usr/bin/env bash
#  vim:ts=4:sts=4:sw=4:et
#
#  Author: Hari Sekhon
#  Date: 2006-06-28 23:25:09 +0100 (Wed, 28 Jun 2006)
#
#  https://github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

# ============================================================================ #
#                                  C u s t o m
# ============================================================================ #

# Stuff that's overly custom and only sourced for my own user
#
# eg. $USER specific env vars and too short less generic aliases

if ! [[ $USER =~ hari|sekhon ]]; then
    return 0
fi

# put secret tokens in vars() or ~/.bashrc.local instead
export GITHUB_USER=HariSekhon
export TRAVIS_USER="HariSekhon"
export BUILDKITE_ORGANIZATION=hari-sekhon
export SEMAPHORE_CI_ORGANIZATION=harisekhon

alias tll="travis_last_log.py"

# can't set this to just the shorter 'go' or 'perl' because it'll clash with the actual commands
alias goto=go_tools
alias pyt=pytools
alias to=perl_tools

# shellcheck disable=SC2154
export plugins="$github/nagios-plugins"
export pl="$plugins"
alias plugins='sti pl; cd $pl'
alias pl=plugins

# travis_last_log.py should be in $PATH from DevOps-Python-tools repo
alias pll="travis_last_log.py HariSekhon/nagios-plugins"
export pl2="${plugins}2"
alias pl2='sti pl2; cd $pl2'

alias pytl="tll /pytools"
alias pyt2="pytools2"
alias pyl="pylib"
alias pyll="tll /pylib"

alias tol="tll /tools"
alias to2="tool2"

# clashes with the D2 diagramming language
#alias d2="Dockerfiles2"
alias Dockerfilesl="tll /Dockerfiles"


================================================
FILE: .bash.d/direnv.sh
================================================
#!/usr/bin/env bash
#  vim:ts=4:sts=4:sw=4:et
#
#  Author: Hari Sekhon
#  Date: 2020-04-10 13:02:46 +0100 (Fri, 10 Apr 2020)
#
#  https://github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

if type -P direnv &>/dev/null; then
    if ! type _direnv_hook &>/dev/null ||
       ! [[ "${PROMPT_COMMAND:-}" =~ _direnv_hook ]]; then
        eval "$(direnv hook bash)"
    fi
fi

# direnv seems to inserts a double semi-colon which breaks PROMPT_COMMAND
#export PROMPT_COMMAND="${PROMPT_COMMAND%%;;*}"
export PROMPT_COMMAND="${PROMPT_COMMAND//;;/;}"

#alias envrc='$EDITOR .envrc && direnv allow .'
# same effect as above
alias envrc='direnv edit'

# allow all .envrc under your current root - use only inside trusted repos
alias direnvallowall='find . -name .envrc -exec direnv allow {} \;'
alias da='direnv allow'
alias daa='direnvallowall'


================================================
FILE: .bash.d/docker.sh
================================================
#!/usr/bin/env bash
#  vim:ts=4:sts=4:sw=4:et
#
#  Author: Hari Sekhon
#  Date: 2015-11-05 20:53:32 +0000
#
#  https://github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

# ============================================================================ #
#                                  D o c k e r
# ============================================================================ #

bash_tools="${bash_tools:-$(dirname "${BASH_SOURCE[0]}")/..}"

# shellcheck disable=SC1090,SC1091
. "$bash_tools/.bash.d/os_detection.sh"

# shellcheck disable=SC1090,SC1091
[ -f ~/.docker_vars ] && . ~/.docker_vars

#if is_linux && type -P podman &>/dev/null; then
#    alias docker="podman"
#fi

export DOCKER_BUILDKIT=1

# for new M1 Macs which otherwise fail to build with errors like this:
#
#   AWS CLI version: qemu-x86_64: Could not open '/lib64/ld-linux-x86-64.so.2': No such file or directory
#
export DOCKER_DEFAULT_PLATFORM=linux/amd64

alias dh=hub-tool
alias dc=docker-compose
alias dps='docker ps'
alias dpsa='docker ps -a'
alias dst="dockerhub_show_tags.py"
# -l shows latest container, -q shows only ID
#alias dl='docker ps -lq'
alias dockerimg='$EDITOR "$bash_tools/setup/docker-images.txt"'

# wipe out exited containers
alias dockerrm='docker rm -- $(docker ps -qf status=exited)'

alias dockerr=dockerrunrm
alias dock=dockerr
alias dockere=dockerexec
alias de=dockere

alias dockerrma=dockerrmall

# wipe out dangling image layers
#alias dockerrmi='docker rmi $(docker images -q --filter dangling=true)'
dockerrmi(){
    # want word splitting here
    # shellcheck disable=SC2046
    docker rmi $(docker images -q --filter dangling=true)
}

# docker-compose -f ...
dcf(){
    local docker_compose_yaml="$1"
    if ! [ -f "$docker_compose_yaml" ] &&
         [ -f "docker-compose.yaml" ]; then
        docker_compose_yaml=docker-compose.yaml
    fi
    shift
    docker-compose -f "$docker_compose_yaml" up "$@"
    docker-compose -f "$docker_compose_yaml" logs -f
}

# starts the docker VM, shows ASCII whale, but slow
#alias dockershell="/Applications/Docker/Docker\ Quickstart\ Terminal.app/Contents/Resources/Scripts/start.sh"
# better
#alias dockervm="VBoxManage controlvm startvm default"
#alias dockervm="docker-machine start default"

#alias dm="docker-machine"
#alias dockerrr="docker-machine restart default"
#alias dockerreload="docker-machine env default > '$bash_tools/.docker_vars'; . '$bash_tools/.docker_vars'"

#dockerstart(){
#    if ! docker-machine status default | grep -q Running; then
#        docker-machine start default
#        sleep 20
#    fi
#    docker start $(cat "$bash_tools/docker-start.txt")
#}

# avoid external commands per shell, slows down new shells and wastes battery
# switched to using ~/.docker_vars file which is cheaper due to less forks and picked up in each new shell
#if type -P docker-machine &>/dev/null; then
#    if docker-machine status default | grep -q -e Started -e Running; then
#        eval $(docker-machine env default)
#    fi
#fi

#alias dockerr="docker run --rm -ti"
function dockerrunrm(){
    local args=()
    local passed_first_non_switch_arg=0  # when this latch gets to level 3 we stop doing prefix processing to not adulterate ls -l / type args
    for x in "$@"; do
        if [ $passed_first_non_switch_arg -lt 3 ]; then
            if [ "${x:0:1}" = "-" ]; then
                passed_first_non_switch_arg=1
            elif [ $passed_first_non_switch_arg -eq 1 ]; then
                passed_first_non_switch_arg=2
            elif [ $passed_first_non_switch_arg -lt 3 ]; then
                if [ "${x:0:1}" = "/" ]; then
                    if [[ "$x" != */Users/* && "$x" != */home/* ]] &&
                       [ "$(strLastIndexOf "$x" / )" -eq 1 ]; then
                        x="harisekhon$x"
                    fi
                fi
                passed_first_non_switch_arg=3
            else
                ((passed_first_non_switch_arg+=1))
            fi
        fi
        args+=("$x")
    done
    # Alpine 2 is dead in the water since the package list repos don't even load any more:
    #
    # # apk update
    # fetch http://dl-4.alpinelinux.org/alpine/v2.7/main/x86_64/APKINDEX.tar.gz
    # wget: server returned error: HTTP/1.1 404 Not Found
    # ERROR: http://dl-4.alpinelinux.org/alpine/v2.7/main: Bad address
    # WARNING: Ignoring APKINDEX.0f59c441.tar.gz: No such file or directory
    #
    #if [[ "$args" =~ alpine:2 ]] && ! [[ "$args" =~ [[:space:]] ]]; then
    #    echo "warning: using alpine:2.* with args but alpine:2.* doesn't have a default CMD so adding 'sh' arg" >&2
    #    args="$args sh"
    #fi
    local basedir="${PWD##*/}"
    docker run --rm -ti -v "$PWD":"/$basedir" -w "/$basedir" "${args[@]}"
}
alias drun='docker run --rm -ti -v "${PWD}":/app'

docker_get_container_ids(){
    local exclude_file=~/docker-perm.txt
    local args=()
    # if exclude file doesn't exist, grep fails entirely and we get no IDs returned, even pre-emptively replacing with /dev/null doesn't work, so omit the option entirely
    if [ -f "$exclude_file" ]; then
        args=(-f "$exclude_file")
    fi
    docker ps -a --format "{{.ID}} {{.Names}}" |
    if [ ${#args} -gt 0 ]; then
        grep -vi "${args[@]}" 2>/dev/null
    else
        cat
    fi |
    awk '{print $1}'
}

dockerrmall(){
    # would use xargs -r / --no-run-if-empty but that is GNU only, doesn't work on Mac
    local ids=()
    read -r -a ids <<< "$(docker_get_container_ids)"
    if [ ${#ids} -gt 0 ]; then
        docker rm -f -- "${ids[@]}"
    fi
}

dockerrmigrep(){
    for x in "$@"; do
        docker images |
        awk "/$x/{print \$1\":\"\$2}" |
        sed '/<none>/d' |
        xargs -r docker rmi --
    done
}

dockerrmgrep(){
    for x in "$@"; do
        docker ps -a |
        grep "$x" |
        awk '{print $NF}' |
        xargs -r docker rm -f --
    done
}

dockerip(){
    docker inspect --format '{{ .NetworkSettings.IPAddress }}' "$@"
}

# this goes to the last created and sometimes exited container
#alias dockere='docker exec -ti $(docker ps -lq) /bin/bash'
dockerexec(){
    if [ $# -gt 0 ]; then
        container="$(docker ps | grep -i "$1" | awk '{print $1}' | head -n1)"
    else
        container="$(docker ps -q | head -n1)"
    fi
    docker exec -ti "$container" /bin/sh
}

docker_get_images(){
    # uniq_order_preserved.pl is in the DevOps-Perl-tools repo on github and should be in the $PATH
    # too many images on dockerhub to pull, fills up filesystem
    #echo "$(dockerhub_search.py harisekhon -n 1000 | tail -n +2 | awk '{print $1}' | sort) $(sed 's/#.*//;/^[[:space:]]*$/d' "$bash_tools/setup/docker-images.txt" | uniq_order_preserved.pl)"
    sed 's/#.*//;/^[[:space:]]*$/d' "$bash_tools/setup/docker-images.txt" |
    uniq_order_preserved.pl
}

dockerpull1(){
    # pull only latest tag, mine first, then official
    local images="${*:-}"
    [ -z "$images" ] && images="$(docker_get_images)"
    images="$(grep -v ":" <<< "$images")"
    whendone "docker pull" # must be first arg so quoted, [l] trick not needed as grep -v grep's
    for image in $images; do
        #whendone "docker pull" # must be first arg so quoted, [l] trick not needed as grep -v grep's
        timestamp "docker pull $image"
        #docker pull "$image" | cat &
        docker pull "$image"
        # wipe out dangling image layers
        dockerrmi
        echo
    done
}
dockerpullgithub(){
    dockerpull1 harisekhon/{nagios-plugins,pytools,tools,centos-github,debian-github,ubuntu-github,alpine-github}
}

dockerpull(){
    local images="${*:-}"
    [ -z "$images" ] && images="$(docker_get_images)"
    dockerpull1 "$images"
    images="$(grep -i -e harisekhon -e ":" <<< "$images")"
    #local images="$(grep -i -e ":" <<< "$images")"
    # now pull all tags, mine first, then official
    whendone "docker pull" # must be first arg so quoted, [l] trick not needed as grep -v grep's
    for image in $images; do
        #whendone "docker pull" # must be first arg so quoted, [l] trick not needed as grep -v grep's
        if [[ "$image" = harisekhon/* && ! "$image" =~ ":" ]]; then
            [[ "$image" =~ presto.*-dev ]] && continue
            for tag in $(dockerhub_show_tags.py -q "$image" | grep -v '^latest$'); do
                timestamp "docker pull $image:$tag"
                #docker pull "$image":"$tag" | cat &
                docker pull "$image":"$tag"
                echo
            done
        else
            timestamp docker pull "$image"
            #docker pull "$image" | cat &
            docker pull "$image"
            echo
        fi
        # wipe out dangling image layers
        dockerrmi
    done
}

dockerpull1r(){
    while true; do
        dockerpull1 "$@"
        wait
        echo -e '\n\nsleeping for 1 hour\n\n'
        sleep 3600
    done
}

dockerpullr(){
    while true; do
        dockerpull "$@"
        wait
        echo -e '\n\nsleeping for 1 hour\n\n'
        sleep 3600
    done
}

# quick, only pull things for which we don't already have local images
dockerpullq(){
    for x in $(docker_get_images); do
        docker images | grep -q "^${x}[[:space:]]" && continue
        whendone "docker pull" # must be first arg so quoted, [l] trick not needed as grep -v grep's
        timestamp docker pull "$x"
        docker pull "$x"
    done
    # wipe out dangling image layers
    dockerrmi
}


================================================
FILE: .bash.d/env.sh
================================================
#!/usr/bin/env bash
# shellcheck disable=SC2230
#  vim:ts=4:sts=4:sw=4:et
#
#  Author: Hari Sekhon
#  Date: circa 2006 (forked from .bashrc)
#
#  https://github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

# ============================================================================ #
#                   E n v i r o n m e n t   V a r i a b l e s
# ============================================================================ #

# more environment variables defined next to the their corresponding aliases in aliases.sh

bash_tools="${bash_tools:-$(dirname "${BASH_SOURCE[0]}")/..}"

# shellcheck disable=SC1090,SC1091
. "$bash_tools/.bash.d/os_detection.sh"

# similar to what zsh does by default
if [ -f ~/.bashenv ]; then
    # shellcheck disable=SC1090,SC1091
    . ~/.bashenv
fi

#export DISPLAY=:0.0

#export TERM=xterm

export EDITOR=vim

export INPUTRC=~/.inputrc

# allow programs to use $LINES and $COLUMNS
export LINES
export COLUMNS

# sets directories to cyan on default bg so they stand out more in dark terminal - see 'man ls' for more details
# works on Mac - you may need to see 'man 5 dir_colors' on Linux
export LSCOLORS="gx"

# ENV refers to the file that sh attempts to read as a startup file (done on my Mac OSX Snow Leopard)
# Needs the following line added to sudoers for ENV to be passed through on sudo su
#Defaults	env_keep += "ENV"
export ENV=~/.bashrc

# ============================================================================ #

cpenv(){
    local env_var="$1"
    if [[ -z "${!env_var}" ]]; then
        echo "Error: Environment variable '$env_var' is not set"
        return 1
    fi
    copy_to_clipboard.sh <<< "${!env_var}"
    echo "Value of '$env_var' has been copied to the clipboard"
}

# Autocomplete function for environment variables
_cpenv_autocomplete() {
    # 'compgen -v' lists all environment variables
    # COMPREPLY is set to the autocomplete options
    local cur_word="${COMP_WORDS[COMP_CWORD]}"
    COMPREPLY=($(compgen -v -- "$cur_word"))
}

# Register autocomplete function for `cpenv`
complete -F _cpenv_autocomplete cpenv


# ============================================================================ #
#             L o c a l e   I n t e r n a t i o n a l i z a t i o n
# ============================================================================ #

# Run this to see available locales:
#
#   locale -a
#
# See details of a specific locale variable eg. time formats:
#
#   LC_ALL=C locale -ck LC_TIME

# aterm doesn't support UTF-8 and you get horrible chars here and there
# so don't use utf and aterm together. xterm works ok with utf8 though
#export LANG=en_GB
#
# LANG becomes default value for any LC_xxx variables not set
#export LANG=C
#
# overrides all other LC_xxx variables
#export LC_ALL=C
#
export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8
export LANGUAGE=en_US.UTF-8
#export LC_ALL=en_GB
# didn't seem to work
#export LANG="en_GB.UTF-8"
#export LC_ALL="en_GB.UTF-8"

# ============================================================================ #

# Clever dynamic environment variables, set using var() function sourced between shells
export varfile=~/.bash_vars
# shellcheck disable=SC1090,SC1091
[ -f "$varfile" ] && . "$varfile"

# Secret Credentials
#
#   separate cred files so if you accidentally expose it on a screen
#   to colleagues or on a presentation or screen share
#   you don't have to change all of your passwords
#   which you would have to if using the above ~/.bash_vars file
if [ -d ~/.env/creds ]; then
    for credfile in ~/.env/creds/*; do
        if [ -f "$credfile" ]; then
            # shellcheck disable=SC1090,SC1091
            . "$credfile"
        fi
    done
fi

#export DISTCC_DIR="/var/tmp/portage/.distcc/"

# ============================================================================ #

if is_mac; then
    #BROWSER=open
    unset BROWSER
elif type -P google-chrome &>/dev/null; then
    BROWSER=google-chrome
elif type -P firefox &>/dev/null; then
    BROWSER=firefox
elif type -P konqueror &>/dev/null; then
    BROWSER=konqueror
elif [ -n "${GOOGLE_CLOUD_SHELL:-}" ]; then
    :
else
    :
    #BROWSER=UNKNOWN
    #echo "COULD NOT FIND ANY BROWSER IN PATH"
fi

# don't export BROWSER on Mac, trigger python bug:
# AttributeError: 'MacOSXOSAScript' object has no attribute 'basename'
# from python's webbrowser library
if ! is_mac; then
    export BROWSER
fi

var(){
    local var="${*%%=*}"
    local val="${*#*=}"
    if grep -i "export $var" "$varfile" &>/dev/null; then
        perl -pi -e 's/^export '"$var"'=.*$/export '"$var"'='"$val"'/' "$varfile"
    else
        echo "export $var=$val" >> "$varfile"
    fi
    export "$var"="$val"
}
vars(){
    "$EDITOR" "$varfile"
    chmod 0600 "$varfile"
    # shellcheck disable=SC1090,SC1091
    . "$varfile"
}

unvar(){
    local var="${*%%=*}"
    [ -f "$varfile" ] || { echo "$varfile not found" ; return 1; }
    perl -pi -e 's/^export '"$var"'=.*\n$//' "$varfile"
    unset "$var"
}

# ============================================================================ #

unsetall(){
    local match="${1:-.*}"
    while read -r env_var; do
        if [ "$env_var" = PATH ]; then
            continue
        fi
        unset "$env_var"
    done < <( env |
        grep -i "$match" |
        sed 's/=.*//' )
}


================================================
FILE: .bash.d/functions.sh
================================================
#!/usr/bin/env bash
# shellcheck disable=SC2230
#  vim:ts=4:sts=4:sw=4:et
#
#  Author: Hari Sekhon
#  Date: circa 2006 (forked from .bashrc)
#
#  https://github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

# ============================================================================ #
#                  B a s h   G e n e r a l   F u n c t i o n s
# ============================================================================ #

bash_tools="${bash_tools:-$(dirname "${BASH_SOURCE[0]}")/..}"

# shellcheck disable=SC1090,SC1091
. "$bash_tools/.bash.d/os_detection.sh"

# Enables colourized return codes in prompt_func
# better leave it as the same as already set. This way a reload of bashrc doesn't change the mode
# could do retmode=${retmode:-off} but this is unnecessary overhead
#retmode=off
# safer to set it to off because otherwise it's possible to get in to a loop with set -u
retmode=${retmode:-off}
retmode(){
    if [ "$retmode" = "on" ]; then
        retmode=off
        echo "retmode off"
    else
        retmode=on
        echo "retmode on"
    fi
}

cddir(){
    cd "$(dirname "$1")" || return 1
}

jq(){
    command jq -CS "$@"
}

envg(){
    env |
    eval grep -i "$(for arg; do echo -n " -e '$arg'"; done)"
}

new(){
    if [ $# -eq 2 ]; then
        title "${2#modules/}"
    else
        title "$1"
    fi
    command new.pl "$@"
    title "$LAST_TITLE"
}

# generates bash autocompletion if not available
# sources bash autocompletion from local standardized path
autocomplete(){
    local name="$1"
    shift || :
    if [ -f ~/.bash.autocomplete.d/"$name.sh" ]; then
        # shellcheck disable=SC1090,SC1091
        . ~/.bash.autocomplete.d/"$name.sh"
    elif type -P "$name" &>/dev/null; then
        # doesn't work
        # shellcheck disable=SC1090,SC1091
        #source <(command "$name" completion bash)
        mkdir -pv ~/.bash.autocomplete.d
        command "$name" completion "$@" bash > ~/.bash.autocomplete.d/"$name.sh"
        # shellcheck disable=SC1090,SC1091
        . ~/.bash.autocomplete.d/"$name.sh"
    fi
}

pg(){
    # don't want pgrep, want color coding
    # shellcheck disable=SC2009
    ps -ef |
    grep -i --color=yes "$@" |
    grep -v grep
}

pstg(){
    # want splitting of options
    # shellcheck disable=SC2086
    pstree |
    grep -5 -i --color=always "$@" |
    less $LESS
}

# externalized to copy_to_clipboard.sh script
#copy_to_clipboard(){
#    if is_mac; then
#        cat | pbcopy
#    elif is_linux; then
#        cat | xclip
#    else
#        echo "ERROR: OS is not Darwin/Linux"
#        return 1
#    fi
#}

unalias clip &>/dev/null || :
# args are optional
# shellcheck disable=SC2120
clip(){
    if [ $# -gt 0 ]; then
        copy_to_clipboard.sh < "$1"
    else
        copy_to_clipboard.sh
    fi
}

dle(){
    if [[ "$PWD" =~ $HOME(/Downloads(/Transmission)?)?$ ]]; then
        echo "Switching to $HOME/Downloads/YouTube"
        mkdir -p -v ~/Downloads/YouTube
        cd ~/Downloads/YouTube || return 1
        if [ -f .envrc ]; then
            eval "$(direnv export bash)"
        fi
    fi
    while true; do
        if BACKGROUND_VIDEO=1 youtube_download_video.sh "$@"; then
            # doesn't persist past a pause/unpause,
            # and this starts playing which we don't want which is why it's backgrounded
            #osascript -e 'tell application "QuickTime Player" to set rate of document 1 to 2' &&
            break
        fi
        local sleep_secs="$((RANDOM % 300))"
        echo "Sleeping for $sleep_secs secs before retrying..."
        sleep "$sleep_secs"
    done
    exit
}
alias ytp="cd ~/Downloads/YouTube && ./play.sh"

deccp(){
    # shellcheck disable=SC2119
    decomment.sh "$@" |
    clip
}

decdiff(){
    diff <(decomment.sh "$1" | sed 's/[[:space:]]*$//') <(decomment.sh "$2" | sed 's/[[:space:]]*$//') "${@:3}"
}

rmdirempty(){
    find "${1:-.}" -type d -empty -exec rmdir "{}" \;
}

checkprog(){
    if type -P "$1" &>/dev/null; then
        return 0
    else
        echo "$1 could not be found in path"
        return 1
    fi
}

function count() {
    local total="$1"
    for ((i = total; i > 0; i--)); do
        sleep 1
        printf "Time remaining %d secs\r" "$i"
    done
    bell
}

dum(){
    du -max "${@:-.}" |
    sort -k1n |
    tail -n 10000
}

typer(){
    local alias_target
    local type_output
    for x in "$@"; do
        type_output="$(type "$x")"
        # shellcheck disable=SC2119
        alias_target="$(
            awk '/aliased to/{print $5}' <<< "$type_output" |
            unquote
        )"
        if [ -n "$alias_target" ]; then
            echo "$type_output"
            typer "$alias_target"
        else
            type "$x"
        fi
    done
}

findup(){
    local arg="$1"
    current_dir="${PWD:-$(pwd)}"
    while [ "$current_dir" != "" ]; do
        if [ -e "$current_dir/$arg" ]; then
            echo "$current_dir/$arg"
            return 0
        fi
        current_dir="${current_dir%/*}"
    done
    echo "Not found in above path: $arg" >&2
    return 1
}

cdup(){
    local arg="$1"
    cd "$(findup "$arg")"
}

lld(){
    {
        local target="$1"
        ls -ld "$target"
        [ "$target" = "/" ] && return
        lld "$(dirname "$target")"
    } | column -t
}

# shellcheck disable=SC2120
unquote(){
    sed '
        s/^[[:space:]]*[`'"'"'"]//;
        s/[`'"'"'"][[:space:]]*$//;
    ' "$@"
}

bell(){
    echo -e '\a'
}

resolve_symlinks(){
    local readlink=readlink
    if is_mac; then
        if type -P greadlink &>/dev/null; then
            readlink=greadlink
        else
            readlink=""
        fi
    fi
    if [ -z "$readlink" ]; then
        echo "$*"
        return
    fi
    for x in "$@"; do
        "$readlink" -m "$x"
    done
}

# for all files listed, return the highest directory - useful for pushd to the right git root following symlinks before doing git diff and commmits, used by gitu() in git.sh which is called in inline vimrc 'nmap ;;'
basedir(){
    local dir_list=""
    for x in "$@"; do
        dir_list="$dir_list $(dirname "$x")"
    done
    # assumes they share the same base and that the shortest one will be right - could put more comparison here and return error if not
    local output
    output="$(tr ' ' '\n'  <<< "$dir_list" | grep -v '^[[:space:]]*$' | sort | head -n 1)"
    if [ -z "$output" ]; then
        echo "ERROR: empty basedir"
        return 1
    fi
    echo "$output"
}

toLower(){
    tr '[:upper:]' '[:lower:]'
}

toUpper(){
    tr '[:lower:]' '[:upper:]'
}

trim(){
    sed 's/^[[:space:]]*//; s/[[:space:]]*$//' "$@"
}

normalize_spaces(){
    # not variant of + \+ works on Mac
    #sed 's/[[:space:]]\+/ /'
    # flattens out newlines, which changes behaviour in scripts like check_git_commit_authors.sh
    #perl -pe 's/\s+/ /g'
    # horizontal newlines, don't match \n
    perl -pe 's/\h+/ /g'
}

remove_last_column(){
    awk '{$NF=""; print $0}'
}

strip_basedirs(){
    local basedir="$1"
    shift
    while read -r filename; do
        filename="${filename#"${basedir%%/}"/}"
        filename="${filename##/}"
        echo "$filename"
    done <<< "$@"
}

user(){
    read -r -p 'user: ' USERNAME
    export USERNAME
    if [ -z "${PASSWORD:-}" ]; then
        pass PASSWORD
    fi
}

pass(){
    # doesn't echo, we can do better by making it star for each char
    #read -r -s -p 'password: ' PASSWORD
    # don't local PASSWORD or default case will not export PASSWORD, changing case to work around
    local password=""
    prompt="Enter password: "
    while IFS= read -p "$prompt" -r -s -n 1 char; do
        if [[ "$char" == $'\0' ]]; then
            break
        fi
        prompt='*'
        password="${password}${char}"
    done
    #passvar="${1:-PASSWORD}"
    for passvar in "${@:-PASSWORD}"; do
        export "$passvar"="$password"
    done
    echo
}

unpass(){
    unset PASSWORD
}

hr(){
    echo "# ============================================================================ #"
}

repeat(){
    local i n
    n="$1"
    shift
    if [ -z "$n" ]; then
        echo "usage: repeat N command args"
        return 1
    fi
    for ((i=1; i <= n; i++)); do
        "$@"
    done
}

loop(){
    while true; do
        eval "${*//\$/\\$}"
        sleep 1
    done
}

ptop(){
    if [ -z "$1" ]; then
        echo "usage: ptop program1 program2 ..."
        return 1
    fi
    local pids
    #pids="$(pgrep -f "$(sed 's/ /|/g' <<< "$*")")"
    pids="$(pgrep -f "${*// /|}")"
    local pid_args=()
    if is_mac; then
        # shellcheck disable=SC2001
        read -r -a pid_args <<< "$(sed 's/^/-pid /' <<< "$pids")"
    else
        # shellcheck disable=SC2001
        read -r -a pid_args <<< "$(sed 's/^/-p /' <<< "$pids")"
    fi
    if [ -z "${pids[*]}" ]; then
        echo "No matching programs found"
        return 1
    fi
    top "${pid_args[@]}"
}

topcommands(){
    # first awk print $2 but my advanced history records `date '+%F %T'` in between number and command for $2 and $3, making command $4
    history |
    awk '{print $4}' |
    awk 'BEGIN {FS="|"} {print $1}' |
    sort |
    uniq -c |
    sort -n |
    tail -n "${1:-10}" |
    sort -nr
}
alias topcmds=topcommands

# easy quick find recursing down current directory tree
#
#f(){
#    [ -n "$*" ] || { echo "usage: f <partial_pattern>"; return 1; }
#    pattern=""
#    for x in $*; do
#        pattern+="*$x"
#    done
#    pattern+="*"
#    find -L . -iname "$pattern"
#}
#
# shellcheck disable=SC2032
f(){
    local grep=""
    # shellcheck disable=SC2013
    for x in "${@//[^A-Za-z0-9_-]/.}"; do
        if [[ "$x" =~ [a-zA-Z0-9._-] ]]; then
            grep="$grep | grep -i --color=auto $x"
        fi
    done
    # times about the same
    #eval find -L . -type f -iname "\*$1\*" $grep
    eval find -L . -type f "$grep"
}

dgrep(){
    local pattern="$*"
    # auto-exported in aliases.sh when iterating git repos
    # shellcheck disable=SC2154
    ls "$docs/"*"${pattern// /}"* 2>/dev/null
    # shellcheck disable=SC2046,SC2033
    grep -iER "$pattern" $(find ~/docs "$docs" -type f -maxdepth 1 2>/dev/null | grep -v '/\.')
}

diffl(){
    diff "$@" | less
}

foreachfile(){
    # not passing function f()
    # shellcheck disable=SC2033
    find . -type f -maxdepth 1 |
    while read -r file; do
        [ ! -f "$file" ] && continue
        [ -b "$file"   ] && continue
        [ -c "$file"   ] && continue
        [ -d "$file"   ] && continue
        [ -p "$file"   ] && continue
        [ -S "$file"   ] && continue
        [ -L "$file"   ] && continue
        "$@"
    done
}

# vim which
# vw() moved to vim.sh

# file which
fw(){
    local path
    for x in "$@"; do
        path="$(which "$x")"
        if [ -z "$path" ]; then
            return 1
        fi
        file "$path"
        echo
        # shellcheck disable=SC2086
        ls -l $LS_OPTIONS "$path"
    done
}

cdwhich(){
    local path
    local directory
    if [ $# -ne 1 ]; then
        echo "usage: cdwhich programname"
        return 1
    fi
    path="$(which "$1")"
    if [ -z "$path" ]; then
        echo
        echo "$1 could not be found in \$PATH"
        return 1
    fi
    directory="$(dirname "$path")"
    if [ -z "$directory" ]; then
        echo "cannot find directory for $path"
        return 2
    fi
    echo "$directory"
    cd "$directory" || return 1
}

whichall(){
    local bin="$1"
    shift || :
    which -a "$bin" |
    while read -r bin; do
        echo -n "$bin: "
        "$bin" "$@"
    done
}

add_etc_host(){
    local host_line="$*"
    # $sudo is set in .bashrc if needed
    # shellcheck disable=SC2154
    $sudo grep -q "^$host_line" /etc/hosts ||
    $sudo echo "$host_line" >> /etc/hosts
}

# vihosts() moved to vim.sh

proxy(){
    export proxy_host="${1:-${proxy_host:-localhost}}"
    export proxy_port="${2:-${proxy_port:-8080}}"
    export proxy_port_ssl="${3:-${proxy_port_ssl:-8443}}"
    export proxy_user="${4:-${proxy_user:-$USER}}"
    if [ -z "$proxy_password" ]; then
        read -r -s -p 'proxy password: ' proxy_password
    fi
    export http_proxy="http://$proxy_user:$proxy_password@$proxy_host:$proxy_port"
    export https_proxy="https://$proxy_user:$proxy_password@$proxy_host:$proxy_port_ssl"
    # MiniShift respects these next three
    export HTTP_PROXY="$http_proxy"
    export HTTPS_PROXY="$https_proxy"
    export NO_PROXY=".local,.localdomain,.intra,169.254.169.254" # works only on suffixes or IP addresses - ignore the EC2 Metadata API address
    export ftp_proxy="$http_proxy" # might need to replace protocol prefix here, would check, but who even uses ftp any more
    JAVA_NO_PROXY="$(sed 's/^/*/;s/,/|*/g' <<< "$NO_PROXY")"
    # strip the additions we just added off the end so that we don't end up with dups if running proxy more than once
    JAVA_OPTS="${JAVA_OPTS%%-Dhttp.proxyHost*}"
    export JAVA_OPTS="$JAVA_OPTS -Dhttp.proxyHost=$proxy_host -Dhttp.proxyPort=$proxy_port -Dhttp.proxyUser=$proxy_user -Dhttp.proxyPassword=$proxy_password -Dhttps.proxyHost=$proxy_host -Dhttps.proxyPort=$proxy_port_ssl -DnonProxyHosts='$JAVA_NO_PROXY'"
    export SBT_OPTS="$JAVA_OPTS"
}

readlink(){
    if is_mac; then
        greadlink "$@"
    else
        command readlink "$@"
    fi
}

abspath(){
    readlink --canonicalize-missing "$1"
}
#abspath(){
#    if [ -z "$1" ]; then
#        echo "NO PATH GIVEN!"
#        return 1
#    fi
#    # shellcheck disable=SC2001
#    sed 's@^\./@'"$PWD"'/@;
#         s@^\([^\./]\)@'"$PWD"'/\1@;
#         s@^\.\./@'"${PWD%/*}"'/@;
#         s@/../@/@g;
#         s@/\./@/@g;
#         s@\(.*\/?\)\.\./?$@\1/@;
#         s@//@/@g;
#         s@/$@@;' <<< "$1"
#}

wcbash(){
    # $github defined in aliases.sh
    # shellcheck disable=SC2154
    wc ~/.bashrc \
       ~/.bash_profile \
       ~/.bash_logout \
       ~/.alias* \
       ~/.aliases* \
       ~/.bashrc_dynamichosts \
       "$github/bash-tools/.bashrc" \
       "$github/bash-tools/.bash_profile" \
       "$github/bash-tools/.bash.d/"*.sh 2>/dev/null
}

epoch2date(){
    if is_mac; then
        date -r "$1"
    else
        date -d "@$1"
    fi
}

pdf(){
    if ! [[ "$1" =~ .*.pdf$ ]]; then
        echo "'$1' does not end in .pdf!"
        return 1
    fi
    if ! [ -f "$1" ]; then
        echo "file not found: $1"
        return 1
    fi
    if is_mac; then
        open "$1"
        return $?
    fi
    for x in acroread evince xpdf; do
        if type -P "$x" &>/dev/null; then
            echo "opening with $x..."
            "$x" "$1" &
            return $?
        fi
    done
    echo "Error cannot find acroread, evince or xpdf in PATH."
    return 1
}

currentScreenResolution(){
    #xrandr | awk '/\*/ {print $1}'
    xdpyinfo  | awk '/dimensions/ {print $2}'
}

yy(){
    cal "$(date '+%Y')"
}

# ============================================================================ #

timestamp(){
    printf "%s" "$(date '+%F %T')  $*"
    [ $# -gt 0 ] && printf '\n'
}
alias tstamp=timestamp

timestampcmd(){
    local output
    output="$("$@" 2>&1)"
    timestamp "$output"
}
alias tstampcmd=timestampcmd

# ============================================================================ #

bak(){
    # TODO: switch this to a .backupstore folder for keeping this stuff instead
    for filename in "$@"; do
        [ -n "$filename" ] || { echo "usage: bak filename"; return 1; }
        [ -f "$filename" ] || { echo "file '$filename' does not exist"; return 1; }
        [[ $filename =~ .*\.bak\..* ]] && continue
        local bakfile
        bakfile="$filename.bak.$(date '+%F_%T' | sed 's/:/-/g')"
        until ! [ -f "$bakfile" ]; do
            echo "WARNING: bakfile '$bakfile' already exists, retrying with a new timestamp"
            sleep 1
            bakfile="$filename.bak.$(date '+%F_%T' | sed 's/:/-/g')"
        done
        cp -av -- "$filename" "$bakfile"
    done
}

unbak(){
    # restores the most recent backup of a file
    for filename in "$@"; do
        #[ -n "$filename" -o "${filename: -4}" != ".bak" ] || { echo "usage: unbak filename.bak"; return 1; }
        [ -n "$filename" ] || { echo "usage: unbak filename"; return 1; }
        #[ -f "$filename" ] || { echo "file '$filename' does not exist"; return 1; }
        local bakfile
        local dirname
        dirname="$(dirname "$filename")"
        filename="${filename##*/}"
        # don't use -t switch, we want the newest by name, not one that got touched recently
        bakfile="$(find "$dirname" -path "*/$filename.bak.*" -o -path "*/$filename.*.bak" 2>/dev/null | sort | tail -n 1)"
        echo "restoring $bakfile"
        cp -av -- "$bakfile" "$dirname/$filename"
    done
}

orig(){
    if [ $# -lt 1 ]; then
        echo "usage: orig file1 file2 file3 ..."
        return 1
    fi
    for filename in "$@"; do
        [ -f "$filename" ] || { echo "file '$filename' does not exist"; return 1; }
        [ -f "$filename.org" ] && { echo "$filename.orig already exists, aborting..."; return 1; }
    done
    for filename in "$@"; do
        cp -av -- "$filename" "$filename.orig"
    done
}

unorig(){
    if [ $# -lt 1 ]; then
        echo "usage: unorig file1.orig file2.orig file3.orig ..."
        return 1
    fi
    for filename in "$@"; do
        if [ -z "$filename" ] || [ "${filename: -5}" != ".orig" ]; then
            echo "usage: unorig filename.orig"
            return 1
        fi
        if ! [ -f "$filename" ]; then
            echo "file '$filename' does not exist"
            return 1
        fi
    done
    for filename in "$@"; do
        cp -av -- "$filename" "${filename%.orig}"
    done
}

# ============================================================================ #

strLastIndexOf(){
    local str="$1"
    local substr="$2"
    local remainder="${str##*"$substr"}"
    local lastIndex=$((${#str} - ${#remainder}))
    echo $lastIndex
}

# ============================================================================ #

progs(){
    # not passing function f()
    # shellcheck disable=SC2033
    find "${@:-.}" -type f |
    grep -Evf ~/code_regex_exclude.txt |
    grep -v -e '/lib/' -e '.*-env.sh' -e '/tests/'
}

progs2(){
    # not passing function f()
    # shellcheck disable=SC2033
    find "${@:-.}" -type f -o -type l |
    grep -Evf ~/code_regex_exclude.txt
}

findpy(){
    # not passing function f()
    # shellcheck disable=SC2033
    find "${@:-.}" -type f -iname '*.py' -o -type f -iname '*.jy' |
    grep -vf ~/code_regex_exclude.txt
}

# ============================================================================ #

ldapmaxuid(){
    ldapsearch -x -W "uidNumber=*" uidNumber |
    sed 's/#.*//' |
    grep -v "^[[:space:]]*$" |
    grep uidNumber |
    sort -k2n |
    tail -n1
}

ldapmaxuidgid(){
    ldapsearch -xW -x -W "(|(objectClass=posixAccount)(objectClass=posixGroup))" uidNumber gidNumber |
    sed 's/#.*//' |
    grep --color=auto -v "^[[:space:]]*$" |
    grep -R --color=auto "(uidNumber|gidNumber)" |
    sort -k2n |
    tail -n1
}


================================================
FILE: .bash.d/gcp.sh
================================================
#!/usr/bin/env bash
#  vim:ts=4:sts=4:sw=4:et
#  shellcheck disable=SC1090,SC1091
#
#  Author: Hari Sekhon
#  Date: 2019-11-14 22:22:35 +0000 (Thu, 14 Nov 2019)
#
#  https://github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

# ============================================================================ #
#              G C P  -  G o o g l e   C l o u d   P l a t f o r m
# ============================================================================ #

srcdir="${srcdir:-$(dirname "${BASH_SOURCE[0]}")/..}"

# shellcheck disable=SC1090,SC1091
#type add_PATH &>/dev/null || . "$srcdir/.bash.d/paths.sh"

# adds GCloud CLI tools to $PATH
if [ -f ~/google-cloud-sdk/path.bash.inc ]; then
    #source ~/google-cloud-sdk/path.bash.inc
    add_PATH ~/google-cloud-sdk/bin  # appends rather than above which prepends to \$PATH, messing up kubectl version requirement for fluxcd
fi

# Bash completion for GCloud CLI tools
if [ -f ~/google-cloud-sdk/completion.bash.inc ]; then
    source ~/google-cloud-sdk/completion.bash.inc
fi

export USE_GKE_GCLOUD_AUTH_PLUGIN=True

# having to retype this way too much
alias gal="gcloud auth login"
# often bugs me to do this
alias gcu="gcloud components update"

alias gce="gcloud compute"
alias gke="gcloud container clusters"
alias gc="gcloud container"
alias gbs="gcloud builds submit --tag"
alias bqq="bq query"
alias gssh="gcloud compute ssh"

# open GCP Console in the current project and preferably on a relevant page if we can detect one
gcpcon(){
    local project
    local path
    # open in the compute instances page if we don't know where else to go
    path="compute/instances"
    if [[ "$PWD" =~ kubernetes|k8 ]]; then
        path="kubernetes/list/overview"
    elif [[ "$PWD" =~ iam ]]; then
        path="iam-admin/iam"
    fi
    project="${CLOUDSDK_CORE_PROJECT:-$(gcloud config get core.project 2>/dev/null)}"
    open "https://console.cloud.google.com/$path?project=$project"
}

# when switching an alias to a function during re-source without un-aliasing, declare function explicitly to avoid errors
function gcloudconfig(){
    # configurations are usually called the same as the project name so export GOOGLE_PROJECT_ID for convenience too
    gcloud config configurations activate "$1" || return 1
    export GOOGLE_PROJECT_ID="$1"
}

gsopen(){
    local gspath="$1"
    gspath="${gspath#gs:\/\/}"
    browser "https://console.cloud.google.com/storage/browser/$gspath"
}

gcropen(){
    local image="$1"
    if ! [[ "$image" =~ gcr\.io/ ]]; then
        echo "'$image' is not a GCR image name (requires gcr.io to know where to open)"
        return 1
    fi
    image="${image%:*}"
    browser "https://$image"
}


================================================
FILE: .bash.d/git.sh
================================================
#!/usr/bin/env bash
#  vim:ts=4:sts=4:sw=4:et
#
#  Author: Hari Sekhon
#  Date: circa 2006 (forked from .bashrc)
#
#  https://github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

# ============================================================================ #
#                   R e v i s i o n   C o n t r o l  -  G i t
# ============================================================================ #

# Primary revision control system
#
# if svn.sh and hg.sh functions are enabled, detects and calls svn and mercurial commands if inside those repos so some of the same commands work dynamically

bash_tools="${bash_tools:-$(dirname "${BASH_SOURCE[0]}")/..}"

if [ -f ~/.github_token  ]; then
    GITHUB_TOKEN="$(cat ~/.github_token)"
    export GITHUB_TOKEN
fi

if [ -f ~/.gitlab_token  ]; then
    GITLAB_API_PRIVATE_TOKEN="$(cat ~/.gitlab_token)"
    export GITLAB_API_PRIVATE_TOKEN
fi
#if [ -z "${GITLAB_API_ENDPOINT:-}" ]; then
#    export GITLAB_API_ENDPOINT="https://gitlab.com/api/v4"
#fi

if ! type basedir &>/dev/null; then
    # shellcheck disable=SC1090,SC1091
    . "$bash_tools/.bash.d/functions.sh"
fi

if type -P gh &>/dev/null; then
    autocomplete gh -s
fi

# shellcheck disable=SC1091
#type add_PATH &>/dev/null || . "$bash_tools/.bash.d/paths.sh"

#add_PATH ~/bin/codeql

# find out who your 'gh' CLI is authenticating as - useful if you have multiple Personal Access Tokens for different environments
alias githubwhoami='github_api.sh /user | jq -r .login'
alias ghwhoami='github_api.sh /user | jq -r .login'

# set location where you check out all the github repos
export github=~/github

export GIT_PAGER="less ${LESS:-}"
# shellcheck disable=SC2230
#if [ -z "${GIT_PAGER:-}" ] && \
if type -P diff-so-fancy &>/dev/null; then
    # pre-loading a pattern to 'n' / 'N' / '?' / '/' search through will force you in to pager and disregard -F / --quit-if-one-screen
    #export GIT_PAGER="diff-so-fancy --color=yes | less -RFX --tabs=4 --pattern '^(Date|added|deleted|modified): '"
    export GIT_PAGER="diff-so-fancy --color=yes | $GIT_PAGER"
fi

alias gitconfig="\$EDITOR ~/.gitconfig"
alias gitignore="\$EDITOR ~/.gitignore_global"
alias gitrc=gitconfig
# false positive, not calling this from xargs
# shellcheck disable=SC2032
#alias add=gitadd
add(){ gitadd "$@"; }
addf(){
    git add -f "$@"
    git ci -m "added $*"
}
alias gadd='git add'
# beware covers up ImageMagick 'import' screenshot command (see HariSekhon/Knowledge-Base mac.md page)
alias import=gitimport
alias co=checkout
alias commit="git commit"
alias clone="git clone"
alias cherry-pick="git cherry-pick"
alias gitci=commit
alias ci=commit
alias gitco=checkout
alias up=pull
alias u=up
alias uu="GIT_PULL_IN_BACKGROUND=1 u"
alias pu=push
alias gitp="git push"
alias gdiff="git diff"
# bypasses diff-so-fancy, could also just pipe through | cat to disable pager and color effects
alias gdiff2="git --no-pager diff"
alias gdiffc="git diff --cached"
alias gdiffm="gdiff origin/master.."
alias gd=gdiff
alias gdc=gdiffc
alias gdo=gdiffm
alias branch="githg branch"
alias br=branch
alias fetch='git fetch'
alias stash="git stash"
alias tag="githg tag"
alias tags='git tag'
alias tagr='git_tag_release.sh'
alias gitlogwc='git log --oneline | wc -l'
alias um=git_submodules_update.sh
#type browse &>/dev/null || alias browse=gbrowse
alias gbrowse=gitbrowse
alias gb='gitbrowse'
alias prbrowse='gh pr view --web'  # uses GitHub CLI
alias prb=prbrowse
#alias gh='gitbrowse github'  # clashes with GitHub CLI
alias gl='gitbrowse gitlab'
alias bb='gitbrowse bitbucket'
alias azd='gitbrowse azure'
alias gha='gitbrowse github actions'
alias ghw='github_workflows'
alias wf='cd $(git_root)/.github/workflows/'
alias ggrep="git grep"
alias gfr='git_foreach_repo.sh'
alias gfrur='git_foreach_repo_update_readme.sh'
alias gfrrra='git_foreach_repo_replace_readme_actions.sh'
alias remotes='git remote -v'
alias remote='remotes'
# much quicker to just 'cd $github; f <pattern>'
#githubls(){
#    # GitHub is svn compatible, use this to list files remotely
#    svn ls "https://github.com/$1.git/branches/master/"
#}
#githubgrep(){
#    for repo in $(sed 's/#.*//;s/:.*//;/^[[:space:]]*$/d' "$srcdir/setup/repos.txt"); do
#        githubls "HariSekhon/$repo"
#    done |
#    grep "$@"
#}

# git fetch -p or git remote prune origin
#alias prune="co master; git pull --no-edit; git remote prune origin; git branch --merged | grep -v -e '^\\*' -e 'master' | xargs git branch -d"
removed_branches(){
    git remote prune origin >&2
    git branch -vv |
    cut -c 3- |
    awk '$4 ~ /gone\]/ {print $1}'
}
alias prune="removed_branches | xargs -r git branch -d"

# don't use this unless you are a git pro and understand unwinding history and merge conflicts
alias GRH="git reset HEAD^"

alias gitnored='git status --ignored'

alias master="switchbranch master"
alias main="switchbranch main"
alias prod="switchbranch prod"
alias production="switchbranch production"
alias staging="switchbranch staging"
alias stage=staging
alias dev="switchbranch dev"
alias develop="switchbranch develop"
alias grp="git_review_push.sh"

# edit all GitHub READMEs
alias readmes='$EDITOR $(git_foreach_repo.sh '"'"'echo $PWD/README.md'"')"
alias readmesi='idea $(git_foreach_repo.sh '"'"'echo $PWD/README.md'"')"
alias ureadmes='git_foreach_repo.sh '"'"'gitu README.md || :'"'"

# equivalent of hg root
# shellcheck disable=SC2120
git_root(){
    local path="${1:-.}"
    local dir
    if [ -f "$path" ]; then
        dir="$(dirname "$path")"
    elif [ -d "$path" ]; then
        dir="$path"
    else
        echo "ERROR: arg passed is not a regular file or directory: $path" >&2
        return 1
    fi
    pushd "$dir" &>/dev/null || return 1
    git rev-parse --show-toplevel
    popd &>/dev/null || return 1
}
alias gitroot=git_root
alias cdgitroot='cd "$(git_root)"'

gitgc(){
    cd "$(git_root)" || :
    if ! [ -d .git ]; then
        echo "not in a git repo, no .git/ directory and git root dir not found"
        return 1
    fi
    du -sh .git
    git gc --aggressive
    du -sh .git
}

git_default_branch(){
    git remote show origin |
    #awk '/^[[:space:]]*HEAD branch:[[:space:]]/{print $3}'
    sed -n '/HEAD branch/s/.*: //p'
}

git_url_base(){
    local filter="${1:-.*}"
    git remote -v |
    { grep "$filter" || : ; }|
    awk '/git@|https:\/\/|ssh:\/\//{print $2}' |
    head -n1 |
    sed 's|^ssh://||;
         s|^https://.*@||;
         s|^https://||;
         s|:[[:digit:]][[:digit:]]*||;
         s/^git@ssh.dev.azure.com:v3/dev.azure.com/;
         s|^git@||;
         s|^|https://|;
         s/\.git$//;
         # Azure DevOps only puts this in https urls, not ssh, so strip for standardizing output
         # Update: actually dont do this because we cannot differentiate internal Azure DevOps
         # by internal fqdn urls so it is better to leave this in
         #s|/_git/|/|;
         ' |
    perl -pe 's/:(?!\/\/)/\//'
}

gitbrowse(){
    local filter="${1:-origin}"
    local path="${2:-}"
    local url_base
    url_base="$(git_url_base "$filter")"
    if [ -z "$url_base" ] && [ "$filter" != origin ]; then
        url_base="$(git_url_base "origin")"
    fi
    if [ -z "$url_base" ]; then
        echo -n "git remote url not found for filter '$filter'"
        if [ "$filter" != "origin" ]; then
            echo " or 'origin'"
        else
            echo
        fi
        return 1
    fi
    if [ -n "$path" ]; then
        path="$(git ls-files --full-name "$path")"
    fi
    if [[ "$url_base" =~ github.com ]]; then
        if [ -z "$path" ]; then
            path+="#readme"
        fi
    else
        if [ -z "$path" ]; then
            local default_branch
            default_branch="$(git_default_branch)"
        fi
        if [[ "$url_base" =~ gitlab.com ]]; then
            if [ -z "$path" ]; then
                url_base+="/-/blob/$default_branch/README.md"
            fi
        elif [[ "$url_base" =~ dev.azure.com ]]; then
            # don't re-add this as it's no longer stripped out in git_url_base
            # because we cannot differentiate internal Azure Devops by fqdn so need to leave it in
            #url_base="${url_base%/*}/_git/${url_base##*/}"
            if [ -z "$path" ]; then
                url_base+="?path=/README.md&_a=preview"
            fi
        elif [[ "$url_base" =~ bitbucket.org ]]; then
            if [ -z "$path" ]; then
                url_base+="/src/$default_branch/README.md"
            fi
        fi
    fi
    url="$url_base"
    if [ -n "$path" ]; then
        if [[ "$url_base" =~ github.com ]]; then
            local default_branch
            default_branch="$(git_default_branch)"
            url+="/blob/$default_branch"
        fi
        url+="/$path"
    fi
    browser "$url"
}

install_git_completion(){
    if ! [ -f ~/.git-completion.bash ]; then
        wget -O ~/.git-completion.bash https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.bash
    fi
}

# shellcheck disable=SC1090,SC1091
[ -f ~/.git-completion.bash ] && . ~/.git-completion.bash

# usage: gi python,perl,go
#        gi list
gitignore_api(){
    local url
    local langs
    local options=()
    local args=()
    # noop - set to use 'tr' to separate items to newlines when given the 'list' arg
    local commas_to_newlines="cat"
    for arg; do
        if [ "$arg" = -- ]; then
            options+=("$arg")
        else
            args+=("$arg")
        fi
    done
    # take args 'python perl', store as 'python,perl' for the API call
    langs="$(IFS=, ; echo "${args[*]}")"
    url="https://www.gitignore.io/api/$langs"
    if [ "$langs" = "list" ]; then
        commas_to_newlines="tr ',' '\\n'"
    fi
    {
    if hash curl 2>/dev/null; then
        curl -sSL "${options[*]}" "$url"
    elif hash wget 2>/dev/null; then
        wget -O - "${options[*]}" "$url"
    fi
    } | eval "$commas_to_newlines"
    echo
}
alias gi=gitignore_api

git_user_repo(){
    git remote -v | awk '{print $2}' | head -n1 | git_repo_strip
}

git_repo(){
    git_user_repo | sed 's|.*/||'
}

github_owner_repo(){
    git remote -v | awk '/github.com/{print $2}' | head -n1 | git_repo_strip
}
github_user_repo(){
    github_owner_repo
}

github_repo(){
    github_user_repo | sed 's|.*/||'
}

git_repo_strip(){
    git_repo_strip_auth | sed 's|.*\.[^:/]*[:/]||; s/\.git[[:space:]]*$//'
}

git_repo_strip_auth(){
    sed 's/[[:alnum:]]*@//'
}

isGit(){
    local target=${1:-.}
    # There aren't local .hg dirs everywhere only at top level so this is difficult in bash
    if [ -d "$target/.git" ]; then
        return 0
    elif [ -f "$target" ] &&
         [ -d "${target%/*}/.git" ]; then
        #-o "$target/../.git" -o "${target%/*}/../.git" ]; then
        return 0
    else
        # This is because git command doesn't return correctly when running from outside git root, complains there is not .git
        if [ -d "$target" ]; then
            pushd "$target" >/dev/null || return 1
            #if [ -n "$(git log -1 . 2>/dev/null)" ]; then
            # better because it will succeed in subdirectories of git repos which are not checked in yet
            if git status &>/dev/null; then
                # shellcheck disable=SC2164
                popd &>/dev/null
                return 0
            fi
        else
            pushd "$(dirname "$target")" >/dev/null || return 1
            #if git log -1 "$target" 2>/dev/null | grep -q '.*'; then
            #if [ -n "$(git log -1 "$(basename "$target")" 2>/dev/null)" ]; then
            # better because it will succeed in subdirectories of git repos which are not checked in yet
            if git status &>/dev/null; then
                # shellcheck disable=SC2164
                popd &>/dev/null
                return 0
            fi
        fi
        # shellcheck disable=SC2164
        popd &>/dev/null
        return 2
    fi
}

git_revision(){
    echo "Revision: $(git rev-parse HEAD)"
}

st(){
  # shellcheck disable=SC2086
  {
    local target="${1:-.}"
    shift
    if ! [ -e "$target" ]; then
        echo "$target does not exist"
        return 1
    fi
    local target_basename
    local target_dirname
    target_basename="$(basename "$target")"
    target_dirname="$(dirname "$target")"
    #if [ -f "Vagrantfile" ]; then
    #    echo "> vagrant status"
    #    vagrant status
    # shellcheck disable=SC2166
    if [ "$target" = "." ] &&
       [ "$PWD" = "$HOME/github" ]; then
        hr
        for x in "$target"/*; do
            [ -d "$x" ] || continue
            pushd "$x" >/dev/null || { echo "failed to pushd to '$x'"; return 1; }
            if git remote -v | grep -qi harisekhon; then
                echo "> GitHub: git status $x $*"
                git status . "$@"
                echo
                hr
                echo
            fi
            # shellcheck disable=SC2164
            popd &>/dev/null
        done
    elif { [ "$target" = "." ] &&
         [ "${PWD##*/}" = work ] ; } ||
         grep -Fxq "$PWD" <<< "${GIT_BASEDIRS:-}" ||
         [ -f .iterate ]; then
         #ls ./*/.git &>/dev/null; then  # matches inside repos with submodules unfortunately
        hr
        for x in "$target"/*; do
            [ -d "$x" ] || continue
            pushd "$x" >/dev/null || { echo "failed to pushd to '$x'"; return 1; }
            echo "> Work: git status $x $*"
            git status . "$@"
            echo
            hr
            echo
            # shellcheck disable=SC2164
            popd &>/dev/null
        done
    elif isGit "$target"; then
        if [ -d "$target" ]; then
            pushd "$target" >/dev/null || { echo "Error: failed to pushd to $target"; return 1; }
            echo "> git stash list" >&2
            git stash list && echo
            #"$bash_tools/git/git_summary_line.sh"
            echo "> git status $target $*" >&2
            #git -c color.status=always status -sb . "$@"
            git -c color.status=always status . "$@"
            echo
            git_revision
            echo
        else
            pushd "$target_dirname" >/dev/null || { echo "Error: failed to pushed to '$target_dirname'"; return 1; }
            echo "> git status $target $*" >&2
            #"$bash_tools/git/git_summary_line.sh"
            git -c color.status=always status "$target_basename" "$@"
        fi
        #git status "$target" "${*:2}"
        # shellcheck disable=SC2164
        popd &>/dev/null
    elif type isHg &>/dev/null && isHg "$target"; then
        echo "> hg status $target $*" >&2
        hg status "$target" "$@" | grep -v "^?"
        # to see relative paths instead of the default absolute paths
        #hg status "$(hg root)"
    elif type isSvn &>/dev/null && isSvn "$target"; then
        echo "> svn st $*" >&2
        svn st --ignore-externals "$target" "$@" | grep -v -e "^?" -e "^x";
    else
        echo "not a revision controlled resource as far as bashrc can tell"
    fi
  } |
  # more calls less on Mac, and gets stuck in interactive mode ignoring the less alias switches
  #more -R -n "$((LINES - 3))"
  #less -RFX
  eval ${GIT_PAGER:-cat}
}

stq(){
    st "$@" | grep --color=no -e "=======" -e branch -e GitHub | eval "${GIT_PAGER:-cat}"
}

# disabling this as I don't use Mercurial or Svn any more,
# replacing with simpler function below that will pass through more things like --rebase
#pull(){
#    local target="${1:-.}"
#    if ! [ -e "$target" ]; then
#        echo "$target does not exist"
#        return 1
#    fi
#    local target_basename
#    target_basename="$(basename "$target")"
#    # shellcheck disable=SC2166
#    if [ "$target_basename" = "github" ] || [ "$target" = "." -a "$(pwd)" = "$github" ]; then
#        for x in "$target"/*; do
#            [ -d "$x" ] || continue
#            # get last character of string
#            [ "${x: -1}" = 2 ] && continue
#            pushd "$x" >/dev/null || { echo "failed to pushd to '$x'"; return 1; }
#            if git remote -v | grep -qi harisekhon; then
#                echo "> GitHub: git pull $x ${*:2}"
#                git pull "${@:2}"
#                echo
#                echo "> GitHub: git submodule update --init --recursive"
#                git submodule update --init --recursive
#                echo
#            fi
#            # shellcheck disable=SC2164
#            popd &>/dev/null
#        done
#        return
#    elif isGit "$target"; then
#        pushd "$target" >/dev/null &&
#        echo "> git pull -v ${*:2}" >&2
#        git pull -v "${@:2}"
#        echo "> git submodule update --init --recursive"
#        git submodule update --init --recursive
#        #local orig_branch=$(git branch | awk '/^\*/ {print $2}')
#        #for branch in $(git branch | cut -c 3- ); do
#        #    git checkout -q "$branch" &&
#        #    echo -n "$branch => " &&
#        #    git pull -v
#        #    echo
#        #    echo
#        #done
#        #git checkout -q "$orig_branch"
#        # shellcheck disable=SC2164
#        popd &>/dev/null
#    elif type isHg &>/dev/null && isHg "$target"; then
#        pushd "$target" >/dev/null &&
#        echo "> hg pull && hg up" >&2  &&
#        hg pull && hg up
#        # shellcheck disable=SC2164
#        popd &>/dev/null
#    elif type isSvn &>/dev/null && isSvn "$target"; then
#        echo "> svn up $target" >&2
#        svn up "$target"
#    else
#        echo "not a revision controlled resource as far as bashrc can tell"
#        return 1
#    fi
#}

# simpler replacement function to above
# shellcheck disable=SC2120
pull(){
    # shellcheck disable=SC2166
    if [ "$PWD" = "$HOME/github" ]; then
        for x in *; do
            [ -d "$x/.git" ] || continue
            # get last character of string - don't pull blah2, as I use them as clean checkouts
            [ "${x: -1}" = 2 ] && continue
            pushd "$x" >/dev/null || { echo "failed to pushd to '$x'"; return 1; }
            if git remote -v | grep -qi "${GITHUB_USER:-${GIT_USER:-${USER:-}}}"; then
                hr
                echo "> GitHub $x: git pull --no-edit $*"
                #echo "> GitHub $x: git submodule update --init --recursive"
                if [ -n "${GIT_PULL_IN_BACKGROUND:-}" ]; then
                    git_pull "$@" &
                else
                    git_pull "$@"
                fi
            fi
            # shellcheck disable=SC2164
            popd &>/dev/null
        done
    elif [ "${PWD##*/}" = work ] ||
         grep -Fxq "$PWD" <<< "${GIT_BASEDIRS:-}" ||
         [ -f .iterate ]; then
         #ls ./*/.git &>/dev/null; then  # matches inside repos with submodules unfortunately
        for x in *; do
            [ -d "$x/.git" ] || continue
            hr
            pushd "$x" >/dev/null || { echo "failed to pushd to '$x'"; return 1; }
            echo "> Work $x: git pull --no-edit $*"
            #echo "> work $x: git submodule update --init --recursive"
            if [ -n "${GIT_PULL_IN_BACKGROUND:-}" ]; then
                git_pull "$@" &
            else
                git_pull "$@"
            fi
            # shellcheck disable=SC2164
            popd &>/dev/null
        done
    else
        echo "> git pull --no-edit $*"
        echo "> git submodule update --init --recursive"
        git_pull "$@"
    fi
}

git_pull(){
    echo
    git pull --no-edit "$@"
    echo
    git submodule update --init --recursive
    echo
}

alias coj="git_branch_jira_ticket"
git_branch_jira_ticket(){
    local ticket="$1"
    local branch="${ticket##*/}"
    if git branch | sed 's/^..//' | grep -Fxq "$branch"; then
        git checkout "$branch"
    else
        git checkout -b "$branch"
    fi
}

checkout(){
    if isGit "."; then
        git checkout "$@";
    else
        echo "not a Git checkout, cannot switch to branch $*"
        return 1
    fi
}

_gitaddimport() {
    local action="$1"
    shift;
    [ -z "$*" ] && return 1
    local basedir
    local trap_codes="INT ERR"
    for filename in "$@"; do
        basedir="$(basedir "$filename")"
        # shellcheck disable=SC2064,SC2086
        trap "popd &>/dev/null; trap - $trap_codes; return 1 2>/dev/null" $trap_codes;
        pushd "$basedir" > /dev/null || return 1;
        # shellcheck disable=SC2086
        filename="$(strip_basedirs "$basedir" "$filename")";
        if ! [ -e "$filename" ]; then
            echo "ERROR: $filename does not exist" >&2
            #return 1
        elif git status -s "$filename" | grep -q '^[?A]'; then
            git add "$filename" &&
            git commit -m "$action $filename" "$filename"
        elif git status -s "$filename" | grep -q '^.M'; then
            echo "ERROR: '$filename' already in git, but has changes, commit as an update instead" >&2
            #return 1
        elif git status --ignored -s "$filename" | grep -q '^!!'; then
            echo "ERROR: '$filename' is ignored!!! =>  $(git check-ignore -v "$filename")" >&2
            #return 1
        else
            echo "ERROR: '$filename' already in git" >&2
            #return 1
        fi
        popd > /dev/null || return 1
    done
}

gitadd(){
    _gitaddimport added "$@"
}

gitimport(){
    _gitaddimport imported "$@"
}


gitu(){
    git_diff_commit.sh "$@"
}
gituu(){
    # avoiding xargs due to function reference:
    # gxargs: gitu: No such file or directory
    eval gitu "$(
        git status --porcelain -s . |
        grep -e '^M' -e '^.M' |
        sed 's/^...//' |
        while read -r filename; do
            echo "\"$filename\""
        done
    )"
}

#githgu(){
#    target="${1:-.}"
#    #count=0
#    while [ -L "$target" ]; do
#        #target="$(readlink "$target")"
#        #let count+=1
#        #if [ $count -gt 10 ]; then
#        #    echo "looping over links more than 10 times in hggitu! "
#        #    exit 2
#        #fi
#        echo "$target is a symlink! "
#        return 1
#    done
#    if ! [ -e "$target" ]; then
#        echo "$target does not exist"
#        return 1
#    fi
#    if isGit "$target"; then
#        echo "> git" >&2
#        #if [ -d "$target" ]; then
#        #    pushd "$target" >/dev/null
#        #else
#        #    pushd "$(dirname "$target")" >/dev/null
#        #fi
#        #"$srcdir2/gitu" "${target##*/}" &&
#        gitu "$target"
#        #popd &>/dev/null
#    elif type isHg &>/dev/null && isHg "$target"; then
#        echo "> hg" >&2
#        #if [ -d "$target" ]; then
#        #    pushd "$target" >/dev/null
#        #else
#        #    pushd "$(dirname "$target")" >/dev/null
#        #fi
#        #"$srcdir2/hgu" "${target##*/}" &&
#        hgu "$target"
#        #popd &>/dev/null
#    # Not supporting SVN any more
#    #elif type isSvn &>/dev/null && isSvn "$target"; then
#    #    echo "> svn" >&2
#    #    svnu "$target"
#    else
#        echo "not a revision controlled resource as far as bashrc can tell"
#        return 1
#    fi
#}

push(){
    # shellcheck disable=SC2119
    pull || return 1
    if isGit .; then
        echo "> git push $*"
        #for remote in $(git remote); do
        #    git push -v $remote $@
        #done
        # can't be sure where we're pushing without parsing the command args, so omit for now
        if [ $# -eq 0 ]; then
            echo "pushing to:"
            # uniq_ordered.pl from my DevOps-Perl-tools repo or
            # uniq2 from my DevOps-Golang-tools repo would be better here
            # but not sure I want to create a dependency on that
            # unix's standard uniq unfortnately will only deduplicate adjacent lines but should be good enough in most cases
            git remote -v | awk '/^origin/{print $1"\t"$2}' | sed 's,://.*@,://,' | uniq
            echo
        fi
        # exposes your Github / GitLab / Bitbucket tokens on the screen, not secure, use printing above instead
        #git push -v "$@"
        git push "$@"
        echo
        st
    elif type isHg &>/dev/null && isHg .; then
        echo "> hg push $*"
        hg push "$@"
    else
        echo "not in a Git or Mercurial controlled directory"
        return 1
    fi
}
unalias pushu 2>/dev/null || :
pushu(){
    if git remote -v | grep -qi '^origin[[:space:]].*gitlab\.'; then
        "$bash_tools/gitlab/gitlab_push_mr_preview.sh"
    else
        "$bash_tools/github/github_push_pr_preview.sh"
    fi
}
unalias pushup 2>/dev/null || :
pushup(){
    if git remote -v | grep -qi '^origin[[:space:]].*gitlab\.'; then
        "$bash_tools/gitlab/gitlab_push_mr.sh"
    else
        "$bash_tools/github/github_push_pr.sh"
    fi
}
unalias pushupmerge 2>/dev/null || :
pushupmerge(){
    if git remote -v | grep -qi '^origin[[:space:]].*gitlab\.'; then
        GITLAB_MERGE_PULL_REQUEST=true \
        "$bash_tools/gitlab/gitlab_push_mr.sh"
    else
        GITHUB_MERGE_PULL_REQUEST=true \
        "$bash_tools/github/github_push_pr.sh"
    fi
}
alias pushupm=pushupmerge

pushr(){
    for remote in $(git remote); do
        echo "> git push \"$remote\""
        git push "$remote"
        echo
    done
}

alias pr=github_pull_request_create.sh

alias mup=masterupdateprune
masterupdateprune(){
    #local master_branch="master"
    #if git branch | sed 's/^..//' | grep -Fx main; then
    #    master_branch="main"
    #fi
    git checkout "$(git_default_branch)"
    pull
    prune
    git_revision
    echo
}

current_branch(){
    git rev-parse --abbrev-ref HEAD
}
alias currentbranch=current_branch

switchbranch(){
    if isGit "."; then
        git checkout "$1";
    elif type isHg &>/dev/null && isHg "."; then
        hg update "$1"
    else
        echo "not a Git / Mercurial checkout, cannot switch to branch $1"
        return 1
    fi
}

gitrm(){
    git rm -- "$@" &&
    git commit -m "removed $*" -- "$@"
}

gitrename(){
    if [ $# -ne 2 ]; then
        echo "usage: gitrename <original_filename> <new_filename>"
        return 1
    fi
    if [ -f "$2" ]; then
        local file_already_exists=1
        mv -iv -- "$2" "$2.tmp"
    fi
    git mv -- "$1" "$2" &&
    git commit -m "renamed $1 to $2" "$1" "$2"
    if [ "${file_already_exists:-}" = 1 ]; then
        mv -fv -- "$2.tmp" "$2"
    fi
}

gitmv(){
    if [ $# -ne 2 ]; then
        echo "usage: gitmv <original_filename> <new_filename>"
        return 1
    fi
    if [ -f "$2" ]; then
        local file_already_exists=1
        mv -iv -- "$2" "$2.tmp"
    fi
    git mv -- "$1" "$2" &&
    git commit -m "moved $1 to $2" "$1" "$2"
    if [ "${file_already_exists:-}" = 1 ]; then
        mv -fv -- "$2.tmp" "$2"
    fi
}

gitd(){
    git diff "${@:-.}"
}

gitadded(){
    git log --name-status "$@" |
    grep -e '^A[^u]' -e '^Date' |
    grep -B 1 '^A' |
    less
}

# doesn't need pipe | less, git drops you in to less anyway
gitl(){
    git log --all --graph --decorate --name-status "$@"
}

gitlp(){
    git log -p "$@"
}
alias gitlp1="gitlp -1"

gitl2(){
    git log --all --graph --decorate --stat "$@"
}

gitl3(){
    git log --pretty=format:"%n%an => %ar%n%s" --name-status "$@"
}

githg(){
    if isGit .; then
        git "$@"
    elif type isHg &>/dev/null && isHg .; then
        hg "$@"
    else
        echo "not a Git/Mercurial checkout"
        return 1
    fi
}

retag(){
    local tag1="$1"
    local checksum="$2"
    local additional_tags="${*:2}"
    for tag in $tag1 $additional_tags; do
        git tag -d "$tag" || :
        echo "Creating git tag '$tag'"
        # quoting checksum causes failure with unrecognized checksum ''
        git tag "$tag" "$checksum"
        git tag |
        grep -qF "$tag" ||
            echo "FAILED"
    done
}

gitfind(){
    local refids
    refids="$(git log --all --oneline | grep "$@" | awk '{print $1}')"
    printf 'Branches:\n\n'
    for refid in $refids; do
        git branch --contains "$refid"
    done | sort -u
    printf '\nTags:\n\n'
    for refid in $refids; do
        git tag --contains "$refid"
    done | sort -u
}

#stagemerge(){
#    if isGit "."; then
#        git checkout prod    && git pull &&
#        git checkout staging && git pull &&
#        git merge prod
#        git checkout prod
#    else
#        echo "Not a Git working copy";
#    fi
#}

gitdiff(){
    local filename="${1:-}"
    [ -n "$filename" ] || { echo "usage: gitdiff filename"; return 1; }
    git diff "$filename" > "/tmp/gitdiff.tmp"
    diffnet.pl "/tmp/hgdiff.tmp"
}

git_author_names(){
    git log --all --pretty=format:"%an" | sort | uniq -c | sort -k1nr | less
}

git_author_emails(){
    git log --all --pretty=format:"%ae" | sort | uniq -c | sort -k1nr | less
}

git_author_names_emails(){
    git log --all --pretty=format:"%an %ae" | sort | uniq -c | sort -k1nr | less
}

git_authors(){
    git_author_emails
}

git_commit_count(){
    # interestingly, even on 10,000 commit repos, there are no duplicate short hashes shown from:
    # git log --all --pretty=format:"%h" | sort | uniq -d
    git log --all --pretty=format:"%h" | wc -l
}

git_revert_typechange(){
    # want splitting to separate filenames
    # shellcheck disable=SC2046
    co $(git status --porcelain -s "${1:-.}" | awk '/^.T/{print $2}')
}

git_rm_untracked(){
    if [ $# -lt 1 ]; then
        echo "usage: rm_untracked <target_dir_or_files_or_glob>"
        return 1
    fi
    # iterate on explicit targets only
    # intentionally not including current directory to avoid accidentally wiping out untracked files - you must specify "rm_untracked ." if you really intend this
    for x in "${@:-}"; do
        git status --porcelain -s --untracked-files=all "$x" |
        # this breaks the correct spacings for Spotify playlist filenames
        #awk '/^\?\?/{$1=""; print}' |
        grep '^??' |
        sed 's/^?? //' |
        while read -r filename; do
            # git status --porcelain double quotes file paths when containing unicode chars which are representated in \xxx format
            # you must set 'git config --global core.quotePath false' for this to work properly
            #
            # this doesn't help because you are still stuck with \xxx chars throughout
            filename="${filename#\"}"
            filename="${filename%\"}"
            rm -v -- "$filename" || break
        done
    done
}

# example of usage of this in the function below - make sure to put '$repo' or "\$repo" somewhere in the argument body to make use of the iteration variable
foreachrepo(){
    local repolist="${REPOLIST:-$bash_tools/setup/repos.txt}"
    while read -r repo; do
        "$@"
    done < <(sed 's/#.*$//; s/.*://; /^[[:space:]]*$/d' "$repolist")
}

github_authors(){
    # deferring expansion into loop
    # shellcheck disable=SC2016
    foreachrepo 'echo "repo: $repo"; pushd "$github/$repo" >/dev/null || return 1; git_authors; popd >/dev/null || return 1; echo' | ${less:-less}
}

merge_conflicting_files(){
    # merge conflicts:
    #
    # UU = both updated
    # AA = both added
    #
    git status --porcelain | awk '/^UU|^AA/{$1=""; print}'
}

merge_deleted_files(){
    git status --porcelain | awk '/^DU/{$1=""; print}'
}

# useful for Dockerfiles merging lots of branches
#
# while ! make mergemasterpull; do fixmerge "merged master"; done
#
fixmerge(){
    local msg="${*:-merged}"
    local merge_conflicted_files
    local merge_deleted_files
    merge_deleted_files="$(merge_deleted_files)"
    if [ -n "$merge_deleted_files" ]; then
        # false positive, not passing add function/alias add to git
        # shellcheck disable=SC2033
        xargs git add <<< "$merge_deleted_files"
    fi
    merge_conflicted_files="$(merge_conflicting_files)"
    if [ -n "$merge_conflicted_files" ]; then
        # shellcheck disable=SC2086
        "$EDITOR" $merge_conflicted_files &&
        git add $merge_conflicted_files
    fi
    git ci -m "$msg"
}

buildkite_browse(){
    if [ -z "${BUILDKITE_ORGANIZATION:-}" ]; then
        echo "\$BUILDKITE_ORGANIZATION not set"
        return 1
    fi
    local repo
    repo="$(git_repo | tr '[:upper:]' '[:lower:]')"
    browser "https://buildkite.com/$BUILDKITE_ORGANIZATION/$repo"
}
# bk is used by buildkite cli now
alias bkb=buildkite_browse


================================================
FILE: .bash.d/golang.sh
================================================
#!/usr/bin/env bash
# shellcheck disable=SC2230
#  vim:ts=4:sts=4:sw=4:et
#
#  Author: Hari Sekhon
#  Date: circa 2015 (forked from .bashrc)
#
#  https://github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

# ============================================================================ #
#                                  G o l a n g
# ============================================================================ #
# Golang

bash_tools="${bash_tools:-$(dirname "${BASH_SOURCE[0]}")/..}"

# unreliable that HOME is set, ensure shell evaluates to the right thing before we use it
[ -n "${HOME:-}" ] || HOME=~

github="${github:-$HOME/github}"

# shellcheck disable=SC1090,SC1091
#type add_PATH &>/dev/null || . "$bash_tools/.bash.d/paths.sh"

# shellcheck disable=SC1090,SC1091
#. "$bash_tools/.bash.d/os_detection.sh"

#export GOPATH="$github/go-tools"
export GOPATH="$HOME/go"
alias gopath='cd "$GOPATH"'
alias gogo='gopath'
alias cdgo='gopath'
alias gosrc='cd "$GOPATH/src"'
alias gobin='cd "$GOPATH/bin"'

alias go-tools='cd "$github/go-tools"; export GOPATH="$github/go-tools"'
alias gtools=go-tools
alias gt=gtools

# already added in paths.sh GitHub section
#add_PATH "$github/go-tools"

add_PATH "$github/go-tools/bin"

if [ -d ~/go/bin ]; then
    add_PATH ~/go/bin
fi

# manual installation of 1.5 mismatches with HomeBrew 1.6 installed to $PATH and
#export GOROOT="/usr/local/go"
# causes:
# imports runtime/internal/sys: cannot find package "runtime/internal/sys" in any of:
# /usr/local/go/src/runtime/internal/sys (from $GOROOT)
# /Users/hari/github/go-tools/src/runtime/internal/sys (from $GOPATH)
if type -P go &>/dev/null; then
    if is_mac; then
        GOROOT="$(dirname "$(dirname "$(greadlink -f "$(type -P go)")")")"
    else
        GOROOT="$(dirname "$(dirname "$(readlink -f "$(type -P go)")")")"
    fi
    export GOROOT
    add_PATH "$GOROOT/bin"
    add_PATH "$GOROOT/libexec/bin"
    add_PATH "$GOPATH/bin"
fi

if type -P colorgo &>/dev/null; then
    alias go=colorgo
fi

alias lsgobin='ls -d ~/go/bin/* "$GOROOT"/{bin,libexec/bin}/* "$GOPATH/bin/"* 2>/dev/null'
alias llgobin='ls -ld ~/go/bin/* "$GOROOT"/{bin,libexec/bin}/* "$GOPATH/bin/"* 2>/dev/null'


================================================
FILE: .bash.d/gpg-agent.sh
================================================
#!/usr/bin/env bash
# shellcheck disable=SC2230
#  vim:ts=4:sts=4:sw=4:et
#
#  Author: Hari Sekhon
#  Date: circa 2006 (forked from .bashrc)
#
#  https://github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

# ============================================================================ #
#                               G P G   A g e n t
# ============================================================================ #

# Pinentry is important, gpg-agent won't work without it.
# pinentry intercepts and stores passphrase.

gpg_agent(){
    if [ $UID != 0 ]; then
        if type -P gpg-agent &>/dev/null; then
            # looks like gpg-agent not longer outputs the pid to stdout to capture
            #GPG_ENV_FILE=~/.gpg-agent.env
            #if [ -f "$GPG_ENV_FILE" ]; then
                # shellcheck disable=SC1090,SC1091
                #. "$GPG_ENV_FILE" > /dev/null

                #GPG_AGENT_PID="${GPG_AGENT_INFO#*:}"
                #GPG_AGENT_PID="${GPG_AGENT_PID%:*}"
                #if ! kill -0 "$GPG_AGENT_PID" > /dev/null 2>&1; then
                #    echo "Stale gpg-agent found. Spawning new agent..."
                #    killall -9 gpg-agent
                #    eval "$(gpg-agent --daemon | tee "$GPG_ENV_FILE")"
                #elif [ "$(ps -p "$GPG_AGENT_PID" -o comm=)" != "gpg-agent" ]; then
                #    echo "gpg-agent PID does not belong to gpg-agent, spawning new agent..."
                #    eval "$(gpg-agent --daemon | tee "$GPG_ENV_FILE")"
                #fi
            if type -P pgrep &>/dev/null; then
                if ! pgrep -qf gpg-agent.*--daemon; then
                    echo "Starting gpg-agent..."
                    killall -9 gpg-agent
                    #eval "$(gpg-agent --daemon | tee "$GPG_ENV_FILE")"
                    gpg-agent --daemon
                fi
            fi
            #clear
        fi
    fi
}
# don't really use this any more anyway so don't bother starting it
#gpg_agent


================================================
FILE: .bash.d/grype.sh
================================================
#!/usr/bin/env bash
#  vim:ts=4:sts=4:sw=4:et
#
#  Author: Hari Sekhon
#  Date: 2022-01-10 17:58:03 +0000 (Mon, 10 Jan 2022)
#
#  https://github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

# ============================================================================ #
#                                   G r y p e
# ============================================================================ #

#set -euo pipefail
[ -n "${DEBUG:-}" ] && set -x

#eval "$(grype completion bash)"

# generates auto-completion file to avoid repeating running auto-completion command, and sources from there
#autocomplete grype


================================================
FILE: .bash.d/hadoop.sh
================================================
#!/usr/bin/env bash
# shellcheck disable=SC2230
#  vim:ts=4:sts=4:sw=4:et
#
#  Author: Hari Sekhon
#  Date: circa 2009+ (forked from .bashrc)
#
#  https://github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

# ============================================================================ #
#                        H a d o o p   E c o s y s t e m
# ============================================================================ #

#srcdir="${srcdir:-$(dirname "${BASH_SOURCE[0]}")/..}"

# shellcheck disable=SC1090,SC1091
#type add_PATH &>/dev/null || . "$srcdir/.bash.d/paths.sh"

# ============================================================================ #
#                                    E n v s
# ============================================================================ #

## ln -s -- /usr/local/hadoop-x.y.z /usr/local/hadoop
## ln -s -- /usr/local/hbase-x.y.z /usr/local/hadoop
## ln -s -- /usr/local/zookeeper-x.y.z /usr/local/zookeeper
#
# #find /usr/local -type d -name 'hadoop-*' -o -type d -name 'hbase-*' -o -type d -name 'zookeeper-*' -maxdepth 1 | while read path; do sudo ln -vfsh "$path" "${path%%-*}"; done
# link_latest '/usr/local/hadoop-*' '/usr/local/hbase-*' '/usr/local/pig-*' '/usr/local/zookeeper-*'
# chown -R hari -- /usr/local/{hadoop,hbase,zookeeper}
# re-enabled HADOOP_HOME for Kite SDK

#export HADOOP_HOME="/usr/local/hadoop"    # Deprecated. Annoying error msgs
#export HADOOP_PREFIX="/usr/local/hadoop"  # Hate this
## For OSX
#export HADOOP_OPTS="$HADOOP_OPTS -Djava.security.krb5.realm= -Djava.security.krb5.kdc="
#export HBASE_OPTS="  $HBASE_OPTS -Djava.security.krb5.realm= -Djava.security.krb5.kdc="
#export HBASE_HOME=/usr/local/hbase
#export PIG_HOME=/usr/local/pig
#export ZOOKEEPER_HOME=/usr/local/zookeeper
#add_PATH "$HADOOP_PREFIX/bin"
#add_PATH "$HBASE_HOME/bin"
#add_PATH "$PIG_HOME/bin"
#add_PATH "$ZOOKEEPER_HOME/bin"

#export MAHOUT_HOME=/usr/local/mahout
## indicates to run locally instead of on Hadoop
#export MAHOUT_LOCAL=true
#add_PATH "$MAHOUT_HOME/bin"

# ============================================================================ #
#                                     C L I
# ============================================================================ #

# Hadoop CLI usability is weak so some conveniences for day to day

alias dfs='hdfs dfs'
alias dfsls='hdfs dfs -ls'

alias yarnapp='yarn application'

alias impala='impala_shell.sh'

# nobody should use hive 1 cli any more, remap it to HS2 beeline
alias hive='beeline.sh'
alias hivezk='beeline_zk.sh'


================================================
FILE: .bash.d/intellij.sh
================================================
#!/usr/bin/env bash
# shellcheck disable=SC2230
#
#  Author: Hari Sekhon
#  Date: 2023-07-26 00:10:06 +0100
#
#  vim:ts=4:sts=4:sw=4:et
#
#  https///github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

# ============================================================================ #
#                                I n t e l l i J
# ============================================================================ #

# requires git.sh for git_root() function

# so that you can open files in IntelliJ from the command line on Mac like so:
#
#   idea <filename>
#
if [ -d "/Applications/IntelliJ IDEA CE.app/Contents/MacOS" ]; then
    add_PATH "/Applications/IntelliJ IDEA CE.app/Contents/MacOS"
fi

alias i='idea'

# wrote find_lock.sh to try to find if IntelliJ uses a lock file in the git project
# whether it's open or not but it found not file existence changes at all
#
# after various experimentation, cannot find a reliable indicator via either process or lockfile
# or any .idea/ file change if IntelliJ has a project dir open or not, surprising
#
#is_intellij_project_open(){
#    local path="$1"
#    if [ -f "$path" ]; then
#        path="$(dirname "$path")"
#    fi
#    local git_root
#    git_root="$(git_root "$path")"
#    if [ -z "$git_root" ]; then
#        echo "Given path is not in a git checkout!!" >&2
#        return 1
#    fi
#    local pid
#    pid="$(lsof -n -c java | awk "/${git_root//\//\\/}/ {print \$2}" | sort -u)"
#    if [ -z "$pid" ]; then
#        return 1
#    fi
#    if ps -ef | awk "\$2 == $pid { print }" | grep -q IntelliJ; then
#        return 0
#    fi
#    return 1
#}
#
#open_intellij_project_if_not_already(){
#    local path="$1"
#    local dir
#    if [ -e "$path" ]; then
#        if ! is_intellij_project_open "$path"; then
#            if [ -f "$path" ]; then
#                dir="$(dirname "$path")"
#            else
#                dir="$path"
#            fi
#            idea_bg_disown "$dir"
#            sleep 1
#        fi
#    fi
#}

idea_bg_disown(){
    nohup command idea "$@" &
    # disowns the first backgrounded command instead of the latest command,
    # so use $! to specify the pid of the latest command in this shell
    disown $!
}

# so that you can quickly open files without them holding your terminal open and spewing Java logs all over your screen
idea(){
    local dir
    for arg in "$@"; do
        # because otherwise README Markdown Preview will not render images with relative paths to images inside project:
        #
        #   https://github.com/HariSekhon/Knowledge-Base/blob/69bb8d4220596e90e6c0e61c48dd8e1b9ffdf720/intellij.md#markdown-images-with-relative-paths-not-displaying-in-preview
        #
        # can't find any reliable method for this function, see comment just above function itself for more details
        #open_intellij_project_if_not_already "$arg"
        # XXX: caveat here - in order to not eat CLI args, we open all args after this loop,
        #      which means multiple markdown files in one command will open in the last project
        #      This will still result in broken markdown preview for any markdown files that are outside
        #      the last project directory which will be ithe foreground window
        if [[ "$arg" =~ \.md$ ]]; then
            dir="$(git_root "$arg" || :)"
            if [ -n "$dir" ]; then
                idea_bg_disown "$dir"
                # give time to settle otherwise race condition of immediate idea_bg_own() call will open the file in the other existing project
                sleep 1
            fi
        fi
    done
    idea_bg_disown "$@"
}

idearoot(){
    idea "$(git_root)"
}
alias idear=idearoot

# if a file does not already exist then IntelliJ opens it in a new light IDE instead of in the current project
touch_idea(){
    touch "$@"
    idea "$@"
}
alias tidea="touch_idea"


================================================
FILE: .bash.d/java.sh
================================================
#!/usr/bin/env bash
# shellcheck disable=SC2230
#  vim:ts=4:sts=4:sw=4:et
#
#  Author: Hari Sekhon
#  Date: Sun Sep 9 21:20:49 2012 +0100
#
#  https://github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

# ============================================================================ #
#                                    J a v a
# ============================================================================ #

bash_tools="${bash_tools:-$(dirname "${BASH_SOURCE[0]}")/..}"

# shellcheck disable=SC1090,SC1091
. "$bash_tools/.bash.d/os_detection.sh"

# shellcheck disable=SC1090,SC1091
#type add_PATH &>/dev/null || . "$bash_tools/.bash.d/paths.sh"

add_PATH CLASSPATH ~/bin/java

# turn off those annoying Java 11 warnings when using Groovy scripting
export GROOVY_TURN_OFF_JAVA_WARNINGS=true

#alias rmclass='rm -fv *.class'
alias rmclass='find . -type f -name "*.class" -exec rm -fv {} \;'

if is_mac; then
    mac_export_java_home(){
        local version="$1"
        local args=()
        local java_home
        local java_library_base="/Library/Java/JavaVirtualMachines"
        local java_home_variable="JAVA_HOME"
        # for cross compiling to be found by gradle build
        if [ -n "$version" ]; then
            args+=(-v "1.$version")
            java_home_variable="JAVA${version}_HOME"
        fi
        if [ -x /usr/libexec/java_home ]; then
            # want arg splutting
            java_home="$(/usr/libexec/java_home "${args[@]}" 2>/dev/null)"
            # $? is fine here thanks shellcheck
            # shellcheck disable=SC2181
            if [ $? -eq 0 ] && [ -d "$java_home" ]; then
                export "$java_home_variable"="$java_home"
                if [ -n "$DEBUG" ]; then
                    echo "Determined $java_home_variable from /usr/libexec/java_home to be '$java_home', update ~/.bashrc to optimize by setting this explicitly" >&2
                fi
            fi
        else
            ## java_home=/Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home
            ## JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Home
            ## JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/Current/Home
            ## JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home
            java_home="$(find "$java_library_base/"*1."$version"* -type d -name 'Home*' 2>/dev/null | tail -n1)"
            if [ -d "$java_home" ]; then
                export "$java_home_variable"="$java_home"
                if [ -n "$DEBUG" ]; then
                    echo "Determined $java_home_variable from searching $java_library_base to be '$java_home', update ~/.bashrc to optimize by setting this explicitly" >&2
                fi
            fi
        fi
    }
    if [ -z "$JAVA_HOME" ]; then
        mac_export_java_home
        mac_export_java_home 7
    fi
elif is_linux; then
    if [ -z "$JAVA_HOME" ]; then
        # RHEL / CentOS
        if type -P alternatives &>/dev/null; then
            java_home="$(alternatives --list | awk '/^java[[:space:]]/{print $3; exit}' | sed 's,\(/jre\)\?/bin/java$,,')"
            if [ -n "$java_home" ]; then
                export JAVA_HOME="$java_home"
            fi
        # Debian / Ubuntu
        elif type -P update-alternatives &>/dev/null; then
            java_home="$(update-alternatives --list java 2>/dev/null | sed 's,\(/jre\)\?/bin/java$,,' | head -n1)"
            if [ -n "$java_home" ]; then
                export JAVA_HOME="$java_home"
            fi
        # Alpine / Other / or if all else fails
        else
            # prefers Sun's JDK to OpenJDK, put it higher in the testing list
            # readlink -f => /etc/alternatives/java_sdk => /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.222.b10-0.el7_6.x86_64
            for java_home in \
                    /usr/java/latest    \
                    /usr/java/latest/jre \
                    /usr/lib/jvm/java \
                    /usr/lib/jvm/java-openjdk \
                    /usr/lib/jvm/jre-openjdk \
                    /usr/lib/jvm/jre \
                    /usr/lib/jvm/default-jvm \
                    ; do       # default-jvm is on Alpine
                if   [ -x "$java_home/bin/java" ]; then
                    export JAVA_HOME="$java_home"
                    break
                fi
            done
            if [ -z "$JAVA_HOME" ]; then
                if [ -n "$DEBUG" ]; then
                    echo "WARNING: failed to find JAVA_HOME" >&2
                fi
                # last ditch effort, this will work with warnings
                if [ -x /usr/bin/java ]; then
                    export JAVA_HOME=/usr
                fi
            fi
        fi
    fi
fi

# haven't used this in many years
#j(){
#    for x in "$@"; do
#        echo "javac $x" &&
#        javac "$x"      &&
#        echo "java ${x%.java} $x"  &&
#        java "${x%.java}" "$x"
#    done
#}

if ! type sdk &>/dev/null && [ -s ~/.sdkman/bin/sdkman-init.sh ]; then
    # shellcheck disable=SC1090,SC1091
    source ~/.sdkman/bin/sdkman-init.sh
fi


================================================
FILE: .bash.d/jenkins.sh
================================================
#!/usr/bin/env bash
#  vim:ts=4:sts=4:sw=4:et
#
#  Author: Hari Sekhon
#  Date: 2021-02-22 17:18:09 +0000 (Mon, 22 Feb 2021)
#
#  https://github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help improve or steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

# ============================================================================ #
#                                 J e n k i n s
# ============================================================================ #

#alias jenkins_cli='java -jar ~/jenkins-cli.jar -s http://jenkins:8080'
alias jenkins-cli='jenkins_cli.sh'

#alias backup_jenkins="rsync -av root@jenkins:/jenkins_backup/*.zip '~/jenkins_backup/'"

# sets Jenkins URL to the local docker and finds and loads the current container's superuser token to the environment for immediate use with jenkins_api.sh
jenkins_local(){
    JENKINS_SUPERUSER_PASSWORD="$(
        docker-compose -p bash-tools -f "$(dirname "${BASH_SOURCE[0]}")/../docker-compose/jenkins.yml" \
            exec -T jenkins-server cat /var/jenkins_home/secrets/initialAdminPassword </dev/null
            # use terminal or gets carriage return and would have to tr -d '\r'
    )"

    export JENKINS_USER=admin
    export JENKINS_PASSWORD="$JENKINS_SUPERUSER_PASSWORD"
    export JENKINS_TOKEN="$JENKINS_PASSWORD"
    export JENKINS_API_TOKEN="$JENKINS_PASSWORD"
    export JENKINS_USER_ID="$JENKINS_USER"
    export JENKINS_URL="http://localhost:8080"
}

alias jenkinspass="jenkins_password.sh | copy_to_clipboard.sh"


================================================
FILE: .bash.d/k3d.sh
================================================
#!/usr/bin/env bash
#  vim:ts=4:sts=4:sw=4:et
#
#  Author: Hari Sekhon
#  Date: 2023-04-03 20:30:17 +0100 (Mon, 03 Apr 2023)
#
#  https://github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

# ============================================================================ #
#                                     K 3 d
# ============================================================================ #

#bash_tools="${bash_tools:-$(dirname "${BASH_SOURCE[0]}")/..}"

# shellcheck disable=SC1090,SC1091
#type add_PATH &>/dev/null || . "$bash_tools/.bash.d/paths.sh"

autocomplete k3d


================================================
FILE: .bash.d/kafka.sh
================================================
#!/usr/bin/env bash
#  vim:ts=4:sts=4:sw=4:et
#
#  Author: Hari Sekhon
#  Date: 2019-07-28 14:46:37 +0100 (Sun, 28 Jul 2019)
#
#  https://github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

# ============================================================================ #
#                                   K a f k a
# ============================================================================ #

srcdir="${srcdir:-$(dirname "${BASH_SOURCE[0]}")/..}"

# shellcheck disable=SC1090,SC1091
#type add_PATH &>/dev/null || . "$srcdir/.bash.d/paths.sh"

for directory in \
    /usr/hdp/current/kafka-broker \
    /usr/local/kafka \
    ; do
    if [ -d "$directory" ]; then
        #export KAFKA_HOME=/usr/local/kafka
        export KAFKA_HOME=/usr/hdp/current/kafka-broker
        add_PATH "$KAFKA_HOME/bin"
        break
    fi
done

# kafka wrapper scripts use underscores instead of dashes so do not conflict with above kafka scripts which appear first in $PATH
# moved to top level now
#kafka_wrappers="$(dirname "${BASH_SOURCE[0]}")/../kafka_wrappers"
#add_PATH "$kafka_wrappers"

# HDP defaults to 8GB, on VMs that often breaks cli commands which try to claim too much ram and fail
export KAFKA_OPTS="${KAFKA_OPTS:-} -Xms1G -Xmx1G"

# there was another setting like KAFKA_KERBEROS_CLIENT I've used before but can't remember, this should work too
#kafka_cli_jaas_conf="$(dirname "${BASH_SOURCE[0]}")/../kafka_wrappers/kafka_cli_jaas.conf"
kafka_cli_jaas_conf="$(dirname "${BASH_SOURCE[0]}")/../kafka_cli_jaas.conf"
export KAFKA_OPTS="${KAFKA_OPTS:-} -Djava.security.auth.login.config=$kafka_cli_jaas_conf"

# ============================================================================ #

# XXX: Enable KAFKA_BROKERS and KAFKA_ZOOKEEPER for convenience
#      of not having to specify them each time when using kafka_wrapper/ commands

# XXX: Must use FQDNs to match Kerberos service principals

# Apache / Cloudera
#export KAFKA_BROKERS="$(hostname -f):9092"

# Hortonworks
#export KAFKA_BROKERS="$(hostname -f):6667"

#export KAFKA_ZOOKEEPERS="$(hostname -f):2181"

# optional - use if chrooting in zookeeper
#export KAFKA_ZOOKEEPER_ROOT=/kafka

# ============================================================================ #

bootstrap_server=""

if [ -n "${KAFKA_BROKERS:-}" ] &&
   ! [[ "$*" =~ --bootstrap-server ]]; then
    # shellcheck disable=SC2034
    bootstrap_server="--bootstrap-server $KAFKA_BROKERS"
fi

broker_list=""
if [ -n "${KAFKA_BROKERS:-}" ] &&
   ! [[ "$*" =~ --broker-list ]]; then
    # shellcheck disable=SC2034
    broker_list="--broker-list $KAFKA_BROKERS"
fi

kafka_zookeeper=""
if [ -n "${KAFKA_ZOOKEEPERS:-}" ] &&
   ! [[ "$*" =~ --zookeeper ]]; then
    # shellcheck disable=SC2034
    kafka_zookeeper="--zookeeper $KAFKA_ZOOKEEPERS"
fi


================================================
FILE: .bash.d/kubernetes.sh
================================================
#!/usr/bin/env bash
#  vim:ts=4:sts=4:sw=4:et
#
#  Author: Hari Sekhon
#  Date: 2019-07-28 14:56:41 +0100 (Sun, 28 Jul 2019)
#
#  https://github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

# ============================================================================ #
#                  K u b e r n e t e s   /   O p e n S h i f t
# ============================================================================ #

bash_tools="${bash_tools:-$(dirname "${BASH_SOURCE[0]}")/..}"

# shellcheck disable=SC1090,SC1091
#type add_PATH &>/dev/null || . "$bash_tools/.bash.d/paths.sh"

for x in kubectl oc helm flux; do
    autocomplete "$x"
done

# minishift oc-env > ~/.minishift.env
if [ -f ~/.minishift.env ]; then
    # remove .minishift.env if it causes errors, which can happen if it was generated when there was no MiniShift VM running
    # shellcheck disable=SC1090,SC1091
    . ~/.minishift.env || rm -f -- ~/.minishift.env
fi

#if [ -f "/usr/local/opt/kube-ps1/share/kube-ps1.sh" ]; then
#    . "/usr/local/opt/kube-ps1/share/kube-ps1.sh"
#    # overriden in prompt.sh which is evaluated later so this is sourced there
#    #PS1='$(kube_ps1)'" $PS1"
#fi

# unreliable that HOME is set, ensure shell evaluates to the right thing before we use it
[ -n "${HOME:-}" ] || HOME=~

add_PATH "${KREW_ROOT:-$HOME/.krew/bin}"

for x in "$bash_tools"/kubernetes*.sh; do
    x="${x##*/}"
    name="${x#kubernetes_}"
    eval "k8s_${name}(){
        '$x' \"\$@\"
    }"
done

# ============================================================================ #

# replaced by function further down
#alias k=kubectl
# still need this autocomplete
complete -F __start_kubectl k

# 'k8s-app' label is set by dashboard creation but who uses that
# false positive, the comma doesn't separate args
# shellcheck disable=SC2054
k8s_get_pod_opts=(-o wide -L app,env --show-labels)

#alias po='k get po "${k8s_get_pod_opts[@]}"'
alias po='k get po'
alias pow='po -o wide'
alias powc='poc -o wide'
alias pocw='poc -o wide'
alias kapply='k apply -f'
alias kapp=kapply
alias kget='k get'
alias kedit='k edit'
alias kdel='k delete'
alias kdelf='kdel -f'
alias wp=watchpods
alias kd=kdesc
alias ke=kubectl_exec.sh
alias kexec=kubectl_exec.sh
alias ke2=kubectl_exec2.sh
alias keg=kubectl_exec_grep.sh
alias kg='k get'
alias ka='k apply'
alias kaf='ka -f'
alias kl='k logs'
alias ktp='k top po'
alias kshell='kube-shell'
alias kubesh='kube-shell'
alias kubeconfig='$EDITOR "${KUBECONFIG:-~/.kube/config}"'
alias kubeconf=kubeconfig

#alias use="k config use-context"
alias contexts="k config get-contexts"
#alias context="k config current-context"
context(){ k config current-context; }
#alias con=context
alias cons=contexts
# contexts has this info and is more useful
#alias clusters="k config get-clusters"

# scripts in kubernetes/ directory that should be added to \$PATH (done automatically by sourcing this repo's .bashrc)
alias kbusybox="kubectl_busybox.sh"
alias kalpine="kubectl_alpine.sh"
alias kcurl="kubectl_curl.sh"
alias kdns="kubectl_dnsutils.sh"

kube_config_isolate(){
    local tmpdir="/tmp/.kube"

    mkdir -pv "$tmpdir"

    local default_kubeconfig="${HOME:-$(cd ~ && pwd)}/.kube/config"
    local original_kubeconfig="${KUBECONFIG:-$default_kubeconfig}"

    # reload safety - do not source from new tmpdir - not necessary for direnv but useful for local sourcing tests
    #if [[ "$original_kubeconfig" =~ $tmpdir ]]; then
    #    echo "ignoring \$KUBECONFIG=$original_kubeconfig, using default home location $default_kubeconfig"
    #    original_kubeconfig="$default_kubeconfig"
    #fi

    # isolate the kubernetes context to avoid a race condition affecting any other shells or scripts
    # epoch is added because $$ and $PPID are direnv sub-processes and may be reused later, so using epoch to add uniqueness
    local epoch
    epoch="$(date +%s)"
    export KUBECONFIG="$tmpdir/config.${EUID:-${UID:-$(id -u)}}.$$.$epoch"

    # load your real kube config to isolated staging area to source the context info
    if [ -f "$original_kubeconfig" ]; then
        cp -v -- "$original_kubeconfig" "$KUBECONFIG"
    elif [ -f "$default_kubeconfig" ]; then
        cp -v -- "$default_kubeconfig" "$KUBECONFIG"
    elif [ -f "$PWD/.kube/config" ]; then
        cp -v -- "$PWD/.kube/config" "$KUBECONFIG"
    elif [ -f "/etc/rancher/k3s/k3s.yaml" ]; then
        cp -v -- "/etc/rancher/k3s/k3s.yaml" "$KUBECONFIG"
    else
        echo "WARNING: failed to find one of:

        $original_kubeconfig
        $default_kubeconfig
        $PWD/.kube/config
        /etc/rancher/k3s/k3s.yaml
    " >&2
    fi
}

# false positive, not using positional parameters
# shellcheck disable=SC2142
alias namespace='k config get-contexts | grep -F "$(kubectl config current-context)" | awk "{print \$5}"'
alias kwhere="{ echo -n 'context: '; context; echo -n 'namespace: '; namespace; }"
alias con='kwhere'

#alias kcd='k config set-context "$(kubectl config current-context)" --namespace'

alias menv='eval $(minikube docker-env)'

# scripts at top level, automatically included in $PATH
alias labels="kubectl_node_labels.sh"
alias taints="kubectl_node_taints.sh"

unalias kcd 2>/dev/null
kcd(){
    if [ $# -lt 1 ] || [ $# -gt 2 ]; then
        echo "usage: kcd <namespace>" >&2
        return 1
    fi
    local namespace="$1"
    echo "Switching to namespace '$namespace'"
    k config set-context "$(kubectl config current-context)" --namespace "$namespace"
}

unalias use 2>/dev/null
use(){
    if [ $# -lt 1 ] || [ $# -gt 2 ]; then
        echo "usage: use <context> [<namespace>]" >&2
        return 1
    fi
    local context="$1"
    local namespace="${2:-}"
    local contexts
    contexts="$(k config get-contexts -o name)"
    if ! grep -Fxq "$context" <<< "$contexts"; then
        #echo "No matching contexts, inferring first partial match"
        context="$(grep -Em1 "$context" <<< "$contexts" || :)"
        if [ -z "$context" ]; then
            echo "Couldn't find any matching context name" >&2
            return 1
        fi
        #echo "Inferred context to be '$context'"
    fi
    #local args=()
    #if [ -n "$namespace" ]; then
    #    args+=(--namespace "$namespace")
    #fi
    #k config use-context "$context" "${args[@]}"
    # less efficient, but more verbose
    k config use-context "$context"
    if [ -n "$namespace" ]; then
        kcd "$namespace"
    fi
}

kubectl_namespace(){
    kubectl config get-contexts | awk '/^\*/{print $5}'
}

#alias poc='po | grep -v Completed'
unalias poc &>/dev/null
poc(){
    po "$@" | grep -v Completed
}

#alias dat='datree test --only-k8s-files --ignore-missing-schemas'
dat(){
    if [ $# -eq 0 ]; then
        find . -type f -iname '*.y*ml' |
        # datree doesn't handle patches well
        grep -v patch |
        tr '\n' '\0' |
        xargs -0 datree test --only-k8s-files --ignore-missing-schemas
    else
        datree test --only-k8s-files --ignore-missing-schemas "$@"
    fi
}
datkust(){
    datree_kustomize_all.sh . -- --enable-helm
}

# kustomize
alias kbuild='kustomize build --enable-helm'
alias kustomizebuilddiff='kbuild | kubectl_create_namespaces.sh; kbuild | kubectl diff -f -'
alias kbuilddiff=kustomizebuilddiff
alias kbuildd=kbuilddiff
alias kbd=kbuildd
alias kda=kustomize_diff_apply.sh

# workaround for the fact that kustomize doesn't accept other filenames
kustomize_build_file(){
    local kustomization="$1"
    if [ -z "$kustomization" ]; then
        echo "usage: kustomize_build_file <something>-kustomization.yaml" >&2
        return 1
    fi
    # because shell completion will stop at the prefix, so allow us to just enter and have it figure out what we're doing
    if ! [ -f "$kustomization" ];then
        if [ -f "${kustomization}kustomization.yaml" ]; then
            kustomization+="kustomization.yaml"
        elif [ -f "${kustomization}-kustomization.yaml" ]; then
            kustomization+="-kustomization.yaml"
        elif [ -f "${kustomization}kustomization.yml" ]; then
            kustomization+="kustomization.yml"
        elif [ -f "${kustomization}-kustomization.yml" ]; then
            kustomization+="-kustomization.yml"
        else
            echo "File not found: $kustomization" >&2
            return 1
        fi
    fi
    local prefix="${kustomization%kustomization.y*ml}"
    prefix="${prefix%-}"
    prefix="${prefix%_}"
    command cp -v -- "$prefix"*.yaml /tmp/ >&2
    cd /tmp >&2 || return 1
    echo >&2
    command mv -v -- "${kustomization##*/}" kustomization.yaml >&2
    echo >&2
    kbuild
    local result=$?
    echo >&2
    cd - >&2 || return 1
    return $result
}
alias kbuildf=kustomize_build_file
alias kbf=kbuildf
kbfa(){
    kbuildf "$@" >/dev/null || return 1
    cd /tmp >&2 || return 1
    kustomize_diff_apply.sh
    cd - >&2 || return 1
}

# copies kustomization and values files while stripping their comments and filename prefixes
kustcp(){
    local name="$1"
    local dir="$2"
    echo "Copying $name-kustomization.yaml to $dir/kustomization.yaml" >&2
    decomment "$name-kustomization.yaml" > "$dir/kustomization.yaml"
    echo "Copying $name-values.yaml to $dir/values.yaml" >&2
    decomment "$name-values.yaml" > "$dir/values.yaml"
    echo "Replacing values filename reference in kustomization.yaml" >&2
    perl -pi -e "s/$name-values\\.yaml/values.yaml/" "$dir/kustomization.yaml"
    echo "Done" >&2
}

# ============================================================================ #

# results in a blank arg which breaks kubectl command
#kubectl_opts=("${KUBECTL_OPTS:-}")
# split KUBECTL_OPTS to array properly
read -r -a kubectl_opts <<< "${KUBECTL_OPTS:-}"
# set K8S_NAMESPACE in local .bashrc or similar files for environments where your ~/.kube/config
# gets regenerated daily with certification authentication from a kerberos login script, which
# resets the 'kcd bigdata' namespace change. This way you automatically send the right namespace every time
if [ "${K8S_NAMESPACE:-}" ]; then
    kubectl_opts+=(-n "$K8S_NAMESPACE")
fi
# TODO: might split this later
oc_opts=("${kubectl_opts[@]:-}")

# ============================================================================ #

# oc() and kubectl() fix future invocations of k() to the each command if you want to explicitly switch between them
oc(){
    export KUBERNETES_CLI=oc
    command oc "${oc_opts[@]}" "$@"
}

kubectl(){
    export KUBERNETES_CLI=kubectl
    # if empty causes 'bash: kubectl_opts[@]: unbound variable', and can't use "${kubectl_opts[@]:-}" default because this results in a blank arg which ruins commands
    if [ -n "${kubectl_opts[*]:-}" ]; then
        command kubectl "${kubectl_opts[@]}" "$@"
    else
        command kubectl "$@"
    fi
}

k(){
    local opts=()
    # more efficient than forking to check history every time
    if [ -n "$KUBERNETES_CLI" ]; then
        case "$KUBERNETES_CLI" in
            kubectl)    opts+=("${kubectl_opts[@]}")
                        ;;
                 oc)    opts+=("${oc_opts[@]:-}")
                        ;;
                  *)    echo "invalid command '$KUBERNETES_CLI' listed in \$KUBERNETES_CLI (must be either 'kubectl' or 'oc' depending on whether you are using straight Kubernetes or OpenShift). Fix the variable or unset it to auto-detect when calling the k() function"
                        return
                        ;;
        esac
        command "$KUBERNETES_CLI" "${opts[@]}" "$@"
    else
        # shellcheck disable=SC2086
        case "$(k8s_or_openshift)" in
                openshift)   command oc "${oc_opts[@]}" "$@"
                             export KUBERNETES_CLI=oc
                             ;;
                    k8s|*)   command kubectl "${kubectl_opts[@]}" "$@"
                             export KUBERNETES_CLI=kubectl
                             ;;
        esac
    fi
}

krun(){
    local image="$1"
    local name="${image//\//-}"
    shift
    # sleep infinity only works on some distros
    k run --generator=run-pod/v1 "$name" --image "$image" -ti -- /bin/sh
}

# use ../kubernetes/kubectl_exec.sh via alias instead
#kexec(){
#    local lines
#    local name="${1//\//-}"
#    if [ -z "$name" ]; then
#        echo "usage: kexec <name>"
#        return 1
#    fi
#    for ((i=0;i<100;i++)); do
#        lines="$(k get po | grep -F "$name")"
#        if [ -z "$lines" ]; then
#            echo "No pods matching name $name found!"
#            return 1
#        fi
#        name="$(awk '$3 ~ /Running/{print $1; exit}' <<< "$lines")"
#        if [ -n "$name" ]; then
#            break
#        fi
#        echo "waiting for pod to start running..."
#        sleep 1
#    done
#    local cmd=(kubectl exec -ti "$name" "$@" -- /bin/sh -c 'if type bash >/dev/null 2>&1; then exec bash; else exec sh; fi')
#    echo "${cmd[*]}"
#    "${cmd[@]}"
#}

klog(){
    local name="$1"
    k logs -f -n "$name" "deploy/$name"
}
klogs(){
    local lines
    local name="${1//\//-}"
    shift || :
    if [ -z "$name" ]; then
        echo "usage: klogs <name>"
        return 1
    fi
    for ((i=0;i<100;i++)); do
        lines="$(k get po | grep -F "$name")"
        if [ -z "$lines" ]; then
            echo "No pods matching name $name found!"
            return 1
        fi
        # often want to see the logs of the last pod restart in 'Crashing' status
        #name="$(awk '$3 ~ /Running/{print $1; exit}' <<< "$lines")"
        name="$(awk '{print $1; exit}' <<< "$lines")"
        if [ -n "$name" ]; then
            break
        fi
        echo "waiting for pod to start running..."
        sleep 1
    done
    echo kubectl logs "$@" "\"$name\""
    k logs "$@" "$name"
}

kfwd(){
    local filter="$1"
    local port="$2"
    local hostport="$3"
    shift
    shift
    shift
    # mind need splitting if it's a filter
    # shellcheck disable=SC2086
    kubectl port-forward $filter "$port" "$hostport" &
    open "http://localhost:$hostport"
}

# looks like both of these work on OpenShift context
#
# 'kubectl get pods'
#
# 'oc get pods'

# figure out if we're using k8s or openshift via most recent commands - return either 'k8s' or 'openshift'
k8s_or_openshift(){
    local last_k8s_cmd
    last_k8s_cmd="$(
        history |
        grep -v history |
        grep -Eo -e '\<oc\>' \
                 -e '\<kubect[l]\>' \
                 -e '\<minikub[e]\>' \
                 -e '\<minishif[t]\>' |
        tail -n 1
    )"
    case "$last_k8s_cmd" in
            oc|minishift)   echo openshift
                            # these end up in a subshell so aren't really useful, set in k() instead
                            #export KUBERNETES_CLI=oc
                            ;;
        kubectl|minikube)   echo k8s
                            #export KUBERNETES_CLI=kubectl
                            ;;
                       *)   echo unknown
                            ;;
    esac
}

oc_get_pods(){
    # shellcheck disable=SC2086
    oc get pods "${k8s_get_pod_opts[@]}"
}

k8s_get_pods(){
    # shellcheck disable=SC2086
    k get pods "${k8s_get_pod_opts[@]}"
}

get_pods(){
    #case "$(k8s_or_openshift)" in
    #        openshift)   oc_get_pods
    #                     ;;
    #              k8s)   k8s_get_pods
    #                     ;;
    #                *)   k8s_get_pods
    #                     ;;
    #esac
    #
    # k8s functions now include k8s vs oc detection, no need for above or would end up double calling k8s_or_openshift
    k8s_get_pods
}
export -f get_pods

get_pod(){
    local filter="${1:-.*}"
    get_pods |
    grep -v '^NAME[[:space:]]' |
    grep Running |
    awk "/$filter/{print \$1; exit}"
}

watchpods(){
    # watch on Mac (brew installed) doesn't have -x switch and doesn't work on even 'export -f function'
    # leave using kubectl call for now as that works on openshift too
    watch "
        echo 'Context: '
        echo
        kubectl config current-context
        echo
        echo
        echo 'Pods:'
        echo
        kubectl " "${kubectl_opts[@]}" " get pods " "${k8s_get_pod_opts[@]:-}" " 2>&1
        echo
    "
}

kdesc(){
    k describe "$@" | less
}

# kdesc pod with grep filter on name for fast describing a pod in the current or given namespace
kdp(){
    local filter="${1:-.*}"
    shift || :
    pod="$(k get po -o name "$@" | grep -Em 1 "$filter")" || return
    kdesc "$pod" "$@"
}

kdelp(){
    k delete pod "$@"
}

# Getting token works on stock Kubernetes but not OpenShift due to stricter defaults
#
# Error from server (Forbidden): secrets is forbidden: User "developer" cannot list secrets in the namespace "kube-system": no RBAC policy matched
# error: resource name may not be empty
#
## even after 'oc login' as system/admin
#
# Error from server (Forbidden): secrets is forbidden: User "system" cannot list secrets in the namespace "kube-system": no RBAC policy matched
# error: resource name may not be empty
#
k8s_get_token(){
    kubectl describe secret -n kube-system "$(kubectl get secrets -n kube-system | awk '/^default-token/ {print $1}')" |
    awk '/^token/ {print $2}'
}

# better than: kubectl config view | grep server
k8s_get_api(){
    local context
    local cluster
    context="$(context)"
    cluster="$(k config view -o jsonpath="{.contexts[?(@.name == \"$context\")].context.cluster}")"
    k config view -o jsonpath="{.clusters[?(@.name == \"$cluster\")].cluster.server}"
    # or if you have jq installed:
    # k get --raw=/api | jq -r '.serverAddressByClientCIDRs[0].serverAddress'
    echo
}

# TODO: path like above to get the current context's cluster
k8s_get_client_cert(){
    awk '/^[[:space:]]*client-cert/{print $2}' ~/.kube/config | head -n 1
}

k8s_get_client_key(){
    awk '/^[[:space:]]*client-key-data/{print $2}' ~/.kube/config | head -n 1
}

k8s_get_ca_cert(){
    awk '/^[[:space:]]*certificate-authority-data/{print $2}' ~/.kube/config | head -n 1
}

# generates files for authenticating to kube-apiserver via curl:
#
# curl --cert client_cert.pem --key client_key.pem --cacert ca_cert.pem https://k8smaster:6443/api/v1/pods
# curl --cert client_cert.pem --key client_key.pem --cacert ca_cert.pem https://k8smaster:6443/api/v1/pods/namespaces/default/pods -XPOST -H 'Content-Type: application/json' -d @pod_defintion.json
k8s_get_keys(){
    # use --decode not -d / -D which varies between Linux and Mac
    k8s_get_client_cert | base64 --decode - > client_cert.pem
    echo "generated client_cert.pem"
    k8s_get_client_key | base64 --decode - > client_key.pem
    echo "generated client_key.pem"
    k8s_get_ca_cert | base64 --decode - > ca_cert.pem
    echo "generated ca_cert.pem"
}

# run kubectl commands against multiple clusters
kclusters(){
    for context in $(kubectl config get-contexts -o=name --kubeconfig clusters.yaml); do
        kubectl "$@" --kubeconfig clusters.yaml --context="$context"
    done
}

# to kubectl apply manifests to both clusters for multi-cluster deployments
kclustersapply(){
    kclusters apply -f "$@"  # eg. manifests
}

# inspired by my class 'when' functions in when.sh
whenpodup(){
    local name="${1:-}"
    shift || :
    if [ -z "$name" ]; then
        echo "usage: whenpodup <name>"
        return 1
    fi
    local count=0
    while ! kubectl get pods "$name" -o 'jsonpath={.status.phase}' | grep -q 'Running'; do
        ((count+=1))
        timestamp "waiting for pod '$name' to come up..."
        if [ $count -gt 22 ]; then
            sleep 10
        else
            sleep 5
        fi
    done
    timestamp "pod '$name' is up"
    "$@"
}


================================================
FILE: .bash.d/linux.sh
================================================
#!/usr/bin/env bash
#  vim:ts=4:sts=4:sw=4:et
#
#  Author: Hari Sekhon
#  Date: 2006 (forked from .bashrc)
#
#  https://github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

# ============================================================================ #
#                                   L i n u x
# ============================================================================ #

# Linux specific bits to not include on Mac

# most of the regular stuff is in the other bash.d/*.sh files

bash_tools="${bash_tools:-$(dirname "${BASH_SOURCE[0]}")/..}"

# shellcheck disable=SC1090,SC1091
. "$bash_tools/.bash.d/os_detection.sh"

is_linux || return

open(){
    if type -P xdg-open &>/dev/null; then
        xdg-open "$@"
    elif sensible-browser &>/dev/null; then
        sensible-browser "$@"
    elif x-www-browser &>/dev/null; then
        x-www-browser "$@"
    elif gnome-open &>/dev/null; then
        gnome-open "$@"
    else
        echo "Neither 'xdg-open' nor 'sensible-browser' were found in \$PATH - install one of them to automatically open this URL:"
        echo
        echo "$*"
        echo
    fi
}

alias reloadXdefaults="xrdb ~/.Xdefaults"

#setxkbmap us

# Assign middle mouse to my Alt Gr key
# TODO:  change this to keysym as keycodes can change between keyboards, to find keymaps do
# xmodmap -pkie

if [ -n "$DISPLAY" ] && ! is_mac; then
    # This caused the left to be remapped, must test and handle better
    #xmodmap -e 'keycode 113 = Pointer_Button2'
    #xmodmap -e 'keycode 113 = Left NoSymbol Left'
    xkbset m
    # Ubuntu 12.04.1 LTS had a bug where it turned off repeat keys on my down arrow, this fixed it
    xkbset repeatkeys 116
fi

rpmqf(){
    rpm -qf "$(readlink -m "$1")"
}

fixtime(){
    # $sudo defined in .bashrc
    # shellcheck disable=SC2154
    $sudo /etc/init.d/ntp stop
    $sudo ntpdate pool.ntp.org
    $sudo /etc/init.d/ntp start
}

getmounts(){
    #grep -e "ext" -e "reiser" -e "fat" -e "ntfs" < /proc/mounts |
    #awk '{ print $2 }'
    awk '/ext|reiser|fat|ntfs|btrfs|xfs/{print $2}'
}

findsuid(){
    for x in $(getmounts); do
        echo "Searching $x for suid programs:"
        # $sudo defined in .bashrc if not root
        # shellcheck disable=SC2154
        $sudo find "$x" -xdev -type f -perm -u+s -exec ls -l {} \;
    done
}

findguid(){
    for x in $(getmounts); do
        echo "Searching $x for guid programs:"
        $sudo find "$x" -xdev -type f -perm -g+s -exec ls -l {} \;
    done
}

findsguid(){
    for x in $(getmounts); do
        echo "Searching $x for suid and guid programs:"
        $sudo find "$x" -xdev -type f \( -perm -u+s -o -perm -g+s \) -exec ls -l {} \;
    done
}

findwritable(){
    for x in $(getmounts); do
        echo "Searching $x for world writeable files:"
        $sudo find "$x" -xdev -type f -perm -o+w -exec ls -l {} \;
    done
}

# ==========================
# When using Samba WinPopups on Linux in Windows workgroups - convenient back in the day but shouldn't be needed today with the plethora of better chat tools
#
#netsend(){ smbclient -M "$1" <<< "${*:2}"; }
#alias ns=netsend
#
# clear pop-ups and alerts if sending instant security alerts
#clearnetsend(){
#    sudo pkill -f sambapopup
#}
#alias cns=clearnetsend
#
#clearxmessage(){
#    while pkill xmessage; do
#        sleep 0.1
#    done
#    while pkill gmessage; do
#        sleep 0.1
#    done
#}
# =========================


================================================
FILE: .bash.d/lolcat.sh
================================================
#!/usr/bin/env bash
#  vim:ts=4:sts=4:sw=4:et
#
#  Author: Hari Sekhon
#  Date: 2019-11-03 11:31:02 +0000 (Sun, 03 Nov 2019)
#
#  https://github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

lolz(){
    exec 1> >(lolcat >&2)
}


================================================
FILE: .bash.d/mac.sh
================================================
#!/usr/bin/env bash
# shellcheck disable=SC2230
#  vim:ts=4:sts=4:sw=4:et
#
#  Author: Hari Sekhon
#  Date: circa 2011 (forked from .bashrc)
#
#  https://github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

# ============================================================================ #
#                           A p p l e   M a c   O S X
# ============================================================================ #

# More Mac specific stuff in adjacent *.sh files, especially network.sh

bash_tools="${bash_tools:-$(dirname "${BASH_SOURCE[0]}")/..}"

# shellcheck disable=SC1090,SC1091
. "$bash_tools/.bash.d/os_detection.sh"

is_mac || return

export HOMEBREW_DISPLAY_INSTALL_TIMES=1
#export HOMEBREW_DEBUG=1
#export HOMEBREW_CLEANUP_MAX_AGE_DAYS=30  # default: 120

# Stops Mac calling update_terminal_cwd() which causes a tonne of noise during set -x tracing
export INSIDE_EMACS=1

export icloud="$HOME/Library/Mobile Documents/com~apple~CloudDocs"
alias icloud="cd '$icloud'"

alias osash="osascript -i"
alias osashell=osash

if [ -x /opt/homebrew/bin/brew ]; then
    # shellcheck disable=SC2046
    eval $(/opt/homebrew/bin/brew shellenv)
fi

date(){
    gdate "$@"
}

xargs(){
    # because --no-run-if-empty is useful
    command gxargs "$@"
}

if ! type tac &>/dev/null; then
    tac(){
        gtac "$@"
    }
fi

# used for Shazaming while on headphones - see:
#
#   https://github.com/HariSekhon/Knowledge-Base/blob/master/audio.md#shazam-songs-while-using-headphones-on-mac
#
# Switches to Multi-Output Device which should already be configured as above and contain your headphones and BlackHole 2ch
#
#alias mshazam='SwitchAudioSource -s "Multi-Output Device"; open -a Shazam'
#alias msound='SwitchAudioSource -s "Multi-Output Device"'
unalias msound 2>/dev/null || :
msound(){
    # because if you have 2 multi-output devices eg.
    #
    # - one using AirPods + Blackhole
    # - another using Speakers + Blackhole
    #
    # then Mac automatically renames "Multi-Output Device" to "Multi-Output Device 1",
    # even if the other multi-output device has already been differentiated, it refuses to let you set
    # it back to the default name, so just determine what the first one is called and use that
    #
    local multi_output_device
    multi_output_device="$(SwitchAudioSource -a | grep -m1 '^Multi-Output Device')"
    #echo "Found first multi-output device: $multi_output_device"
    echo "Using first found multi-output device"
    SwitchAudioSource -s "$multi_output_device"
}

alias restartsound='sudo killall coreaudiod'

alias mshazam='msound; open -a Shazam'

vol(){
    if [ $# -ne 1 ]; then
        echo "usage: vol <num>"
        return 1
    fi
    osascript -e "set volume output volume $1"
}

# put in inputrc for readline
#set completion-ignore-case on

# Apple default in Terminal is xterm
#export TERM=xterm
# not sure why I set it to linux
#export TERM=linux
#ulimit -u 512

dhcprenew(){
    local interface="${1:-en0}"
    watch -q 1 ifconfig "$interface"
    sudo scutil <<< "add State:/Network/Interface/$interface/RefreshConfiguration temporary"
    watch ifconfig "$interface"
}

dhcpdiscover(){
    local interface="${1:-en0}"
    watch -q 1 ifconfig "$interface"
    sudo ipconfig set "$interface" BOOTP
    sudo ipconfig set "$interface" DHCP
    watch ifconfig "$interface"
}

macsleep(){
    sudo pmset sleepnow
}

nosleep(){
    echo "Running: caffeinate -s $*"
    echo "(works even if you close the Macbook lid but will still sleep on battery power)"
    caffeinate -s "$@"
}

silence_startup(){
    sudo nvram SystemAudioVolume=%80
}

top(){
    local opts=(-F -R -o)
    if [ $# -eq 1 ]; then
        command top "${opts[@]}" "$1"
    elif [ $# -gt 1 ]; then
        command top "$@"
    else
        command top "${opts[@]}" cpu
    fi
}

fixvbox(){
    sudo /Library/StartupItems/VirtualBox/VirtualBox restart
}

fixaudio(){
    sudo kextunload /System/Library/Extensions/AppleHDA.kext
    sudo kextload   /System/Library/Extensions/AppleHDA.kext
}

showhiddenfiles(){
    defaults write com.apple.finder AppleShowAllFiles YES
    # must killall Finder after this
}

alias reloadprefs='killall -u $USER cfprefsd'
alias strace="dtruss -f"
alias usbinfo='system_profiler SPUSBDataType'
alias vlc="/Applications/VLC.app/Contents/MacOS/VLC"


# clear paste buffer
clpb(){
    copy_to_clipboard.sh < /dev/null
}

macmac(){
    ifconfig |
    awk '
        /^en[[:digit:]]+:/{gsub(":", "", $1); printf "%s:\t", $1}
        /^[[:space:]]ether[[:space:]]/{print $2}
    ' |
    # filters to only the lines with prefixed interfaces from first match
    grep '\t'
}

duall(){
    # bash_tools defined in .bashrc
    # shellcheck disable=SC2154
    du -ax "$bash_tools" | sort -k1n | tail -n 2000
    sudo du -ax / | sort -k1n | tail -n 50
}
alias dua=duall
if type -P brew &>/dev/null; then
    brew_prefix="$(brew --prefix)"
    if [ -f "$brew_prefix/etc/bash_completion" ]; then
        # shellcheck disable=SC1090,SC1091
        . "$brew_prefix/etc/bash_completion"
    fi
fi

brewupdate(){
    if ! brew update; then
        echo "remove the following to brew update"
        brew update 2>&1 | tee /dev/stderr | grep '^[[:space:]]*Library/Formula/' |
        while read -r formula; do
            echo rm -fv -- "/usr/local/$formula"
        done
        return 1
    fi
}

brewinstall(){
    brewupdate &&
    sed 's/#.*// ; /^[[:space:]]*$/d' < ~/mac-list.txt |
    while read -r pkg; do
        brew install "$pkg" #||
            #{ echo "FAILED"; break; }
    done
}

brew_find_unlinked_bins(){
     for x in /usr/local/Cellar/*/*/bin/*; do
         if ! [ -f "/usr/local/bin/${x##*/}" ]; then
             echo "$x"
        fi
    done
}

# don't export BROWSER on Mac, trigger python bug:
# AttributeError: 'MacOSXOSAScript' object has no attribute 'basename'
# from python's webbrowser library
#export BROWSER="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
#export BROWSER="/Applications/Firefox.app/Contents/MacOS/firefox"

# MacPorts - using HomeBrew instead in recent years
#if [ -e "/sw/etc/bash_completion" ]; then
#    . /sw/etc/bash_completion
#fi

# seems Mac OS X has a native pkill now
#pkill(){
#    local args=""
#    local regex=""
#    local grep_args=""
#    while [ -n "$1" ]; do
#        case "$1" in
#            -i) grep_args="$grep_args -i"
#                shift
#                ;;
#            -*) args="$args $1"
#                shift
#                ;;
#             *) regex="$1"
#                shift
#                ;;
#        esac
#    done
#    # TODO: check this a few times and then remove the echo
#    local proclist=$(ps -e | awk '{printf $1 OFS;for(i=4;i<=NF;i++)printf $i OFS;print""}' | grep $grep_args "$regex")
#    if [ -n "$proclist" ]; then
#        echo "$proclist"
#        awk '{print $1}' <<< "$proclist" | xargs echo kill $args
#        read -r -p "Kill all these processes? [y/N] " answer
#        if [ "$answer" = "y" ]; then
#            awk '{print $1}' <<< "$proclist" | xargs kill $args
#        fi
#    fi
#}


================================================
FILE: .bash.d/mercurial.sh
================================================
#!/usr/bin/env bash
#  vim:ts=4:sts=4:sw=4:et
#
#  Author: Hari Sekhon
#  Date: circa 2012 (forked from .bashrc)
#
#  https://github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

# ============================================================================ #
#             R e v i s i o n   C o n t r o l  -  M e r c u r i a l
# ============================================================================ #

type -P hg &>/dev/null || return 0

alias hgi=hgignore
alias hgrc='$EDITOR ~/.hgrc'

# HG doesn't record dirs and there is no .hg per subdir, rather than traverse upwards checking filesystem boundaries use hg tools themselves
isHg(){
    local target="${1:-.}"
    # There aren't local .hg dirs everywhere only at top level so this is difficult in bash
    #if [ -d "$target/.hg" -o -d "$(dirname "$target")/.hg" ]; then
    # shortcut for efficiency
    if [ -d "$target/.hg" ] ||
       [ -d "${target%/*}/.hg" ]; then # || hg parents "$target" &>/dev/null; then # can only call this on files not dirs anyway since Hg doesn't track dirs
        return 0
    #elif [ -f "$target" ] && hg parents "$target"; then
    #    return 0
    #elif hg status "$target" &>/dev/null; then # Doesn't work at all always returns 0 if a subdir of a repo and just blank even if in ignores
        # Unfortunately the -P switch only supports a single pattern so we can't use --file
        #grep -qP -f "$(hg root)/.hgignore"
        # algorithm horribly inefficient, was going to rewrite in perl isHg.pl but see futher down
        #while read regex; do
        #    grep "^[[:space:]]*$" <<< "$regex" && continue
        #    abs_path="$(abs_path "$target")"
        #    abs_path="${abs_path/$(hg root)\/}"
        #    grep -qP "$regex" <<< "$abs_path" && return 1
        #done < "$(hg root)/.hgignore"
    #    return 0
    #elif [ -d "$target" ]; then
    #    echo "WARNING: cannot call hg on a dir, $target is a dir so this returns false and will fall through"
    #    return 1
    # finally found a reasonably efficient way to handle all cases
    # trick to return False on subdirs which are not handled by Mercurial
elif [ -n "$(hg log --limit 1 "$target" 2>/dev/null)" ]; then
        return 0
    else
        return 1
    fi
}

hgignore(){
    #pushd "$srcdir" &>/dev/null
    local hgroot
    hgroot="$(hg root)"
    [ -n "$hgroot" ] || return 1
    "$EDITOR" "$hgroot/.hgignore"
    #popd &>/dev/null
}

hgci(){
    local hgcimsg=""
    for x in "$@"; do
        if hg st "$x" | grep -q "^[?A]"; then
            hgcimsg+="$x, "
        fi
    done
    [ -z "$hgcimsg" ] && return 1
    hgcimsg="${hgcimsg%, }"
    hgcimsg="added $hgcimsg"
    hg add -- "$@" &&
    echo "committing $*"
    hg ci -m "$hgcimsg" -- "$@"
}

hgrm(){
    hg rm -- "$@" &&
    hg ci -m "removed $*" -- "$@"
}

hgrevertrm(){
    hg revert "$@"
    rm -v -- "$@"
}

hgrename(){
    hg mv -- "$1" "$2" &&
    hg ci -m "renamed $1 to $2" -- "$1" "$2"
}

hgmv(){
    hg mv -- "$1" "$2" &&
    hg ci -m "moved $1 to $2" -- "$1" "$2"
}

hgl(){
    hg log "$@" | less
}

hgu(){
    [ -n "$1" ] || { echo "ERROR: must supply arg"; return 1; }
    [ "$(hg diff "$@" | wc -l)" -gt 0 ] || return
    hg diff -- "$@" | more &&
    read -r &&
    echo "committing $*" &&
    hg ci -m "updated $*" -- "$@"
}

#hhgu(){
#    # all playlists end in \n from now on via paste_playlists.sh fix
#    [ -n "$1" ] || { echo "ERROR: must supply arg"; return 1; }
#    pushd "$music" >/dev/null
#    spotify/validate_playlists.sh "$1" || { echo "Playlist validation failed"; return 1; }
#    spotify/validate_playlist_lengths.sh "$1" || { echo "Playlist dump length validation failed"; return 1; }
#    [ `hg st "$1" "spotify/$1" | wc -l` -gt 0 ] || { echo "No changes in either uri or track lists"; return 0; }
#    local target="${1##*/}"
#    local target_tip="$(dirname "$target")/.$(basename "$target").tip"
#    hg cat "$target" | spotify/normalize_tracknames.pl > "$target_tip"
#    cat "$target" | spotify/normalize_tracknames.pl > ".$target"
#    if [ -z "$(diff -iwu "$target_tip" ".$target")" ]; then
#        echo "Noop changes only, committing..."
#        hg mydiff "$target" |
#        #egrep '^\+' | tee /dev/stderr |
#        grep -v '^[+-][+-][+-]' # | sl --no-locking
#        hg ci -m "updated $target" "$target" "spotify/$target"
#        return $?
#    elif diff -iwu "$target_tip" ".$target" | grep -q '^-[^-]'; then
#        local diffs="$(
#        { hg mydiff "$target"
#          hg mydiff "spotify/$target"
#        })"
#        local removals="$(grep -c "^-[^-]" <<< "$diffs")"
#        local additions="$(grep -c "^+[^+]" <<< "$diffs")"
#        diffs="$(echo "$diffs" |
#        egrep "^[+-]" |
#        spotify/normalize_tracknames.pl |
#        diffnet.pl -iw
#        )"
#        if [ -z "$diffs" ]; then
#            echo "Noop changes to tracks, committing..."
#        elif ! echo "$diffs" | grep -q '^-[^-]'; then
#            echo "Net diff shows only playlist additions, committing..."
#            echo "$diffs" |
#            more
#        else
#            {
#            echo "$additions additions $removals removals"
#            echo "$diffs"
#            } |
#            more &&
#            read || return
#        fi
#        hg ci -m "updated $target" "$target" "spotify/$target"
#    else
#        echo "Only playlist additions detected, committing..."
#        hg mydiff "$target" |
#        #grep -v '^[+-][+-][+-]'
#        egrep "^[+-]"
#        hg ci -m "updated $target" "$target" "spotify/$target"
#        return $?
#    #    echo "No additions or removals detected, playlist dump must currently be in progress"
#    #    return 1
#    fi
#    popd &>/dev/null
#}

# equiv to using the 3rd party shelve extension since HG doesn't have this Git Stash functionality
hgshelve(){
    local hgroot
    hgroot="$(hg root)"
    [ -f "$hgroot/shelve.diff" ] &&
        { echo "$hgroot/shelve.diff already exists, aborting for safety to not lose changes"; return 1; }
    hg diff > "$hgroot/shelve.diff"
    hg revert -a
}

# Then merge, hg up etc, then unshelve

hgunshelve(){
    hg import --no-commit "$hgroot/shelve.diff" # && rm -v "$srcdir/shelve.diff"
}

hgdiff(){
    local filename="${1:-}"
    [ -n "$filename" ] || { echo "usage: hgdiff filename"; return 1; }
    hg diff -- "$filename" > "/tmp/hgdiff.tmp"
    diffnet.pl "/tmp/hgdiff.tmp"
}


================================================
FILE: .bash.d/mp3.sh
================================================
#!/usr/bin/env bash
#  vim:ts=4:sts=4:sw=4:et
#
#  Author: Hari Sekhon
#  Date: 2020-07-21 11:36:49 +0100 (Tue, 21 Jul 2020)
#
#  https://github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

# set the Track number metadata on mp3 files in the order that they are given
# see much better mp3_set_track_order.sh at top level of this repo now
#mp3_renumber(){
#    local i=0
#    for x in "$@"; do
#        ((i+=1))
#        id3v2 --track "$i" "$x"
#    done
#}

mp3info(){
    find "${@:-.}" -type f -iname '*.mp3' |
    head -n 1 |
    while read -r filename; do
        mediainfo "$filename"
    done
}

mp3infotail(){
    find "${@:-.}" -type f -iname '*.mp3' |
    tail -n 1 |
    while read -r filename; do
        mediainfo "$filename"
    done
}

mp3infoheadtail(){
    find "${@:-.}" -type f -iname '*.mp3' |
    sed -n '1p;$p' |
    while read -r filename; do
        mediainfo "$filename"
    done
}

mp3set(){
    if [ $# != 2 ]; then
        echo "usage: mp3set <artist> <album>"
        return 1
    fi
    local artist="$1"
    local album="$2"
    mp3_set_artist.sh "$artist"
    mp3_set_album.sh  "$album"
    mp3_set_track_order.sh
    mp3_set_track_name.sh
}


================================================
FILE: .bash.d/mysql.sh
================================================
#!/usr/bin/env bash
#  vim:ts=4:sts=4:sw=4:et
#
#  Author: Hari Sekhon
#  Date: 2020-03-16 13:26:50 +0000 (Mon, 16 Mar 2020)
#
#  https://github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

# ============================================================================ #
#                                   M y S Q L
# ============================================================================ #

bash_tools="${bash_tools:-$(dirname "${BASH_SOURCE[0]}")/..}"

# shellcheck disable=SC1090,SC1091
. "$bash_tools/.bash.d/os_detection.sh"

# shellcheck disable=SC1090,SC1091
type pass &>/dev/null ||
. "$bash_tools/.bash.d/functions.sh"

# highest priority env var first, common one second - export as both
alias mysqlpass='pass MYSQL_PWD MYSQL_PASSWORD'


================================================
FILE: .bash.d/network.sh
================================================
#!/usr/bin/env bash
# shellcheck disable=SC2230
#  vim:ts=4:sts=4:sw=4:et
#
#  Author: Hari Sekhon
#  Date: circa 2006 - 2012 (forked from .bashrc)
#
#  https://github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

# ============================================================================ #
#                                 N e t w o r k
# ============================================================================ #

bash_tools="${bash_tools:-$(dirname "${BASH_SOURCE[0]}")/..}"

# shellcheck disable=SC1090,SC1091
. "$bash_tools/.bash.d/os_detection.sh"

alias 4="ping 4.2.2.1"
alias 8="ping 8.8.8.8"

alias ping="ping -n"
alias p="ping"

pingwait="-w"
is_mac && pingwait="-W"

alias ping_google="while true; do ping www.google.com && sleep 1 || break; done"
alias g=ping_google

# watch_url.pl is in DevOps-Perl-tools repo which should be in $PATH
alias watchu="watch_url.pl"
# watch google
# https because http often gets intercepted by routers + proxies giving false 200 OKs where there is an internet issue
alias wg="watch_url.pl https://google.com"

alias speedtesturl="browser https://speedtest.net"

# ============================================================================ #
#                         Y o u r   I P   A d d r e s s
# ============================================================================ #

# local/internal IP address
myip(){
    ifconfig | grep 'inet[[:space:]]' | grep -v 127.0.0.1 | awk '{print $2}'
}

# public IP address
ifconfigco(){
    curl ifconfig.co
    # something else to consider with jq for lat/long coordinates, ASN, country etc
    #curl ifconfig.co/json
}

ipinfo(){
    # returns json without /ip with region, reverse dns hostname, city, region, country, lat/long coordinates, org, postcode, timezone
    curl ipinfo.io/ip
}

ipify(){
    curl http://api.ipify.org/
    echo
}

# doesn't welcome automation / curl - requires captchas now so obsolete
#whatismyip(){
#    #lynx -dump $(lynx -dump www.whatismyip.com | tail -n 1)
#    lynx -useragent="Mozilla" -dump www.whatismyip.com 2>/dev/null | awk '/Your Public IPv[46] is:/ {print $6}'
#}

# ============================================================================ #
#                               F u n c t i o n s
# ============================================================================ #

checkhost(){
    if [ -z "$1" ]; then
        echo "usage: checkhost hostname/ip"
        return 1
    fi
    if grep -qi "unknown host" <<< "$(ping -c 1 "$pingwait" 1 "$1" 2>&1)"; then
        echo "Unknown host"
        return 1
    fi
}

n(){
    if type -P host &>/dev/null; then
        host "$@"
    elif type -P nslookup &>/dev/null; then
        nslookup "$@"
    else
        echo "neither host nor nslookup were found in the path"
        return 1
    fi
}
alias h=n

getip(){
    host "$@" | grep "has address" | awk '{print $4; exit}'
}

tping(){
    while true; do
        #echo -n "`date '+%F %T'`   "
        local output
        output="$(ping -c 1 "$pingwait" 2 "$@" |
                  grep -v -e statistics \
                          -e "transmitted" \
                          -e "rtt min/avg/max/mdev" \
                          -e "bytes of data" \
                          -e "^[[:space:]]*$" \
                          -e "^PING " \
                          -e "round-trip"
                 )"
        echo "$(date '+%F %T')   ${output:-no response from $1}"
        sleep 1
    done
}
tpinggw(){
    tping "$(get_gw)" "$@"
}

# for trying to find those damn wifi capture portals that disappear but block your internet http proxying
opengw(){
    local gateway
    gateway="$(get_gw)"
    open "http://$gateway"
    open "https://$gateway"
}

port(){
    if [ -z "$2" ]; then
        echo "You must supply a hostname/ip address to test followed by a port number"
        return 1
    fi
    #sudo nmap $1 -p $2 ${@:3} -P0 | grep tcp
    nc -zv "$1" "$2" 2>&1 | grep -v "DNS fwd/rev misma" | sed 's/[^]]*\] //'
}

testport(){
    if [ -z "$2" ]; then
        echo "You must supply a hostname/ip address to test followed by a port number"
        return 1
    fi
    while true; do
        timestampcmd port "$1" "$2"
        sleep 1
    done
}

hammerport(){
    for i in {1..500}; do
        printf "%-3s: " "$i"
        nc -z -v "$1" "$2"
    done
}

halfopen(){
    while true; do
        echo -n "half-open connections: "
        netstat -ant | grep c SYN_RECV
        sleep 1
    done
}

get_gw(){
    local gw
    #gw="$(netstat -rn | awk '/^default.*\./ {print $2;exit}')"
    gw="$(
        netstat -rn |
        awk '
            /^default.*\./ { print $2; exit }
            $1 == "Internet:" { inet = 1; next }
            $1 == "Internet6:" { inet = 0 }
            inet && ($1 == "default" || $1 == "0.0.0.0") && $2 ~ /^[0-9.]+$/ {
                print $2
                exit
            }
        '
    )"
    if [ -z "$gw" ]; then
        echo "Could not find gateway, no default route! " >&2
        return 1
    fi
    echo "$gw"
}

gw(){
    local gw
    gw="$(get_gw)"
    [ -n "$gw" ] || return 1
    ping "$gw"
}


z(){
    local gw
    gw="$(get_gw)"
    if [ -n "$gw" ]; then
        whenup "$gw" &&
        whenup 4.2.2.1 &&
        whenup www.google.com echo "INTERNET OK"
    else
        echo "Couldn't find gateway, cannot test upstream connectivity!"
        return 1
    fi
}

browser(){
    if [ -n "${BROWSER:-}" ]; then
        "$BROWSER" "$@"
    elif is_mac; then
        open "${*:-http://google.com}"
    else
        echo "\$BROWSER environment variable not set and not on Mac OSX, not sure which browser to use, aborting..."
        return 1
    fi
}

browse(){
    if isGit . &>/dev/null && git remote -v | grep -qi http; then
        gitbrowse "$@"
    else
        browser "$@"
    fi
}

downorjustme(){
    browser "http://www.downforeveryoneorjustme.com/$1"
}

# directs to the same as downorjustme
isupme(){
    browser "http://www.isup.me/$1"
}

chrome(){
    if is_mac; then
        # opens in most recent Chrome window
        # could use one of these: --new --args --incognito --new-window
        open -a 'Google Chrome' "${*:-http://www.google.com}"
    else
        checkprog google-chrome || return 1
        google-chrome "${*:-http://www.google.com}" &
    fi

}

ff(){
    if is_mac; then
        open -a 'Firefox' "http://${*:-www.google.com}"
    else
        checkprog firefox || return 1
        firefox "${*:-http://www.google.com}" &
    fi
}

gg(){
    if [ -z "$*" ]; then
        browser &
    else
        searchterm="${*// /%20}"
        browser "http://www.google.com/search?q=$searchterm" &
    fi
}

netcraft(){
    checkprog firefox || return 1
    browser "http://uptime.netcraft.com/up/graph?site=$*" &
}

wikipedia(){
    checkprog "firefox" || return 1
    local searchterm
    searchterm="${*// /%20}"
    browser "http://en.wikipedia.org?search=$searchterm&go=Go" &
}
alias wiki=wikipedia

definition(){
    checkprog "firefox" || return 1
    local searchterm
    searchterm="${*// /%20}"
    # hl=en&q=test&btnI=I%27m+Feeling+Lucky&meta=&aq=f
    browser "http://www.google.co.uk/search?hl=en&q=definition+$searchterm&btnI=I%27m+Feeling+Lucky" &
}
# alias def=definition

# gh(){
#     url="http://www.google.com/search?q="
#     browser "${url}site%3A$*" &
#     browser "${url}site%3A$* login" &
#     browser "${url}link%3A$*" &
#     browser "${url}related%3A$*" &
# }


retry(){
    local cmd="$1"
    local host="${2##*@}"
    #local user="${2%%@*}"
    local args=("${@:3}")
    if [ -z "$host" ]; then
        echo "You must supply a hostname or ip address to connect to"
        return 2
    fi
    if [ "$cmd" = "ssh" ] || [ "$cmd" = "rdp" ]; then
        whenup "$host" || return 1
    fi
    #[ "$cmd" = "ssh" ] && host="root@$host"
    if [ "$cmd" = "ssh" ]; then
        until port "${host##*@}" 22 >/dev/null; do
            tstamp "trying $host port 22"
            sleep 1
        done
    elif [ "$cmd" = "rdp" ]; then
        until port "$host" 3389 >/dev/null; do
            tstamp "trying $host port 3389"
            sleep 1
        done
    fi
    [ "$cmd" = "ssh" ] && printargs="" || printargs="${args[*]}"
    until "$cmd" "$host" "${args[@]}"; do
        sleep 1
        tstamp "trying $cmd $host $printargs"
    done
    echo >/dev/null
}


rdp(){
    if is_mac; then
        "/Applications/Remote Desktop Connection.app/Contents/MacOS/Remote Desktop Connection" "$@" &
    else
        [ -n "$1" ] || return 1
        local resolution="800x600"
        if [ "$(xdpyinfo | awk '/dimensions/ {print $2}' | sed 's/x.*//')" -gt 1024 ]; then
            resolution="1024x768"
        fi
        if type -P krdc &>/dev/null; then
            krdc "rdp:/$WINDOWSDOMAIN\\$WINDOWSUSER@$*" &
            exit 0
        elif type -P rdesktop &>/dev/null; then
            rdesktop -u "$WINDOWSUSER" -d "$WINDOWSDOMAIN" "$@" -g "$resolution" &
            exit 0
        else
            echo  "Could not find krdc or rdesktop in path"
            return 1
        fi
    fi
}

rerdp(){
    retry "whenport $1 3389; rdp" "$1"
}


# ============================================================================ #
#                                   L i n u x
# ============================================================================ #

if is_linux; then

    ipl(){
        iptables -L | nl
    }

fi


# ============================================================================ #
#                                 M a c   O S X
# ============================================================================ #

if ! is_mac; then
    return
fi

dnsservers(){
    scutil --dns | grep 'nameserver\[[0-9]*\]' | sort -u
}

flushdns(){
    dscacheutil -flushcache
    sudo killall -HUP mDNSResponder
}
alias flushcache=flushdns

#APPLE_INTERFACES="Ethernet Airport"
#APPLE_INTERFACES="$(networksetup -listallnetworkservices | grep -E 'Ethernet|Wi-Fi')"
unset APPLE_INTERFACES

get_apple_interfaces(){
    networksetup -listallnetworkservices | grep -E 'Ethernet|Wi-Fi'
}

# Cisco AnyConnect set these rules which mess up my ability to connect directly to VirtualBox VMs on HostOnly Networking
cleardeny(){
    sudo ipfw delete "$(sudo ipfw list | grep deny | awk '{print $1}')"
}
ipfwqflush(){
    sudo ipfw -q flush
}

isMacNetworkService(){
    local interface="$1"
    if [ "$interface" != "Thunderbolt Ethernet" ] &&
       [ "$interface" != "Wi-Fi" ]; then
        echo "interface must be one of Thunderbolt Ethernet or Wi-Fi"
        return 1
    fi
}

set_dns(){
    get_apple_interfaces |
    while read -r interface; do
        sudo networksetup -setdnsservers "$interface" "$@"
    done
}

set_dns_search(){
    get_apple_interfaces |
    while read -r interface; do
        sudo networksetup -setsearchdomains "$interface" "$@"
    done
}

set_dns_search_empty(){
        set_dns_search "Empty"
}
# this wasn't found as an alias from another function
clear_dns_search(){
    set_dns_search_empty
}

function publicdns(){
    set_dns 4.2.2.1 4.2.2.2 4.2.2.3 4.2.2.4 4.2.2.5 4.2.2.6
    set_dns_search_empty
}

function dhcpdns(){
    clear_dns_search # hangs without this as I think it tries to query DNS for all the suffixes in the list
    set_dns "Empty"
    #networksetup -setsearchdomains <networkservice> <domain1> [domain2]
}

get_wifi_interface(){
    networksetup -listnetworkserviceorder |
    grep "Hardware.*Wi-Fi" |
    sed 's/.*: //;s/)$//'
}

get_wifi_network(){
    networksetup -getairportnetwork "$(get_wifi_interface)" | sed 's/^Current Wi-Fi Network: //'
}

set_wifi_network(){
    networksetup -setairportnetwork "$(get_wifi_interface)" "$*"
}

wifi(){
    if [ $# -eq 1 ]; then
        airport on
        set_wifi_network "$1"
    elif [ $# -eq 0 ]; then
        get_wifi_network
    else
        echo "usage: wifi <network>"
        return 1
    fi
}

wifi_networks_preferred(){
    networksetup -listpreferredwirelessnetworks "$(get_wifi_interface)"
}

airport(){
    networksetup -setairportpower "$(get_wifi_interface)" "$1"
}
alias air=airport

airportr(){
    airport off
    airport on
}
alias airr=airportr
alias ag="airr; g"

watchwifi(){
    scnum 39
    while true; do
        checkwifi
        sleep 30 || break
    done
}

checkwifi(){
    # needs to be global otherwise will be forgotten between runs of this program
    [ -z "$wifi_failures" ] && wifi_failures=0
    for((i=1;i<=3;i++)); do
        if ping -c1 -W1 4.2.2.1 >/dev/null; then
            if [ "$wifi_failures" -gt 0 ]; then
                tstamp "wifi recovered from $wifi_failures failures"
            fi
            wifi_failures=0
            return
        else
            ((wifi_failures+=1))
            tstamp "$wifi_failures wifi failures"
        fi
    done
    timestamp "RESTARTING WIFI"
    airportr
}

setdhcp(){
    isMacNetworkService "$1" || return 1;
    sudo networksetup -setdhcp "$1"
}

renewdhcp(){
    sudo ipconfig set "$1" DHCP
}

#sethomenet(){
#    isMacNetworkService "$1" || return 1;
#    sudo networksetup -setmanual "$1" x.x.x.x 255.255.255.0 x.x.x.1
#    sudo route delete 0.0.0.0
#    sudo route add 0.0.0.0 x.x.x.1
#    publicdns
#}


================================================
FILE: .bash.d/nodejs.sh
================================================
#!/usr/bin/env bash
# shellcheck disable=SC2230
#  vim:ts=4:sts=4:sw=4:et
#
#  Author: Hari Sekhon
#  Date: circa 2019 (forked from .bashrc)
#
#  https://github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

# ============================================================================ #
#                                    N o d e
# ============================================================================ #

bash_tools="${bash_tools:-$(dirname "${BASH_SOURCE[0]}")/..}"

# shellcheck disable=SC1090,SC1091
#. "$bash_tools/.bash.d/os_detection.sh"

#type add_PATH &>/dev/null || . "$bash_tools/.bash.d/paths.sh"

# output from 'npm bin'
if [ -d ~/node_modules/.bin ]; then
    add_PATH ~/node_modules/.bin
fi

if [ -d "$bash_tools/node_modules/.bin" ]; then
    add_PATH "$bash_tools/node_modules/.bin"
fi

alias lsnodebin='ls -d ~/node_modules/.bin/* 2>/dev/null'
alias llnodebin='ls -ld ~/node_modules/.bin/* 2>/dev/null'


================================================
FILE: .bash.d/os_detection.sh
================================================
#!/usr/bin/env bash
#  vim:ts=4:sts=4:sw=4:et
#
#  Author: Hari Sekhon
#  Date: circa 2010 - 2012 (forked from .bashrc)
#
#  https://github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

type is_linux &>/dev/null &&
type isMac &>/dev/null &&
type isGoogleCloudShell &>/dev/null &&
type isAzureCloudShell &>/dev/null &&
return

get_os(){
    if [ -z "${operating_system:-}" ] ||
       ! [[ "$operating_system" =~ ^(Linux|Darwin)$ ]]; then
        operating_system="$(uname -s)"
        export operating_system
    fi
}

isLinux(){
    [ -n "${LINUX:-}" ] && return 0
    get_os
    if [ "$operating_system" = Linux ]; then
        export LINUX=1
        return 0
    fi
    return 1
}

isMac(){
    [ -n "${OSX:-}" ] && return 0
    get_os
    if [ "$operating_system" = Darwin ]; then
        export APPLE=1
        export OSX=1
        return 0
    fi
    return 1
}

isGoogleCloudShell(){
    [ -n "${GOOGLE_CLOUD_SHELL:-}" ] && return 0
    get_os
    [ "$operating_system" = Linux ] || return 1
    # DEVSHELL_PROJECT_ID is more likely to be unique to GCP Cloud Shell environment
    #if [ -n "${GOOGLE_CLOUD_PROJECT:-}" ]; then
    if [ -n "${DEVSHELL_PROJECT_ID:-}" ]; then
        export GOOGLE_CLOUD_SHELL=1
        return 0
    fi
    return 1
}

isAzureCloudShell(){
    [ -n "${AZURE_CLOUD_SHELL:-}"  ] && return 0
    get_os
    [ "$operating_system" = Linux ] || return 1
    if [ -n "${ACC_TERM_ID:-}" ]; then
        export AZURE_CLOUD_SHELL=1
        return 0
    fi
    return 1
}

# for compatibility to use the same names as non-interactive lib/
is_linux(){
    isLinux
}

is_mac(){
    isMac
}

is_google_cloud_shell(){
    isGoogleCloudShell "$@"
}

is_azure_cloud_shell(){
    isAzureCloudShell "$@"
}

# make this safe to import in set -e scripts
is_linux || :
isMac || :
isGoogleCloudShell || :
isAzureCloudShell || :


================================================
FILE: .bash.d/paths.sh
================================================
#!/usr/bin/env bash
# shellcheck disable=SC2230
#  vim:ts=4:sts=4:sw=4:et
#
#  Author: Hari Sekhon
#  Date: circa 2006 (forked from .bashrc)
#
#  https://github.com/HariSekhon/DevOps-Bash-tools
#
#  License: see accompanying Hari Sekhon LICENSE file
#
#  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
#  https://www.linkedin.com/in/HariSekhon
#

# ============================================================================ #
#                                   $ P A T H
# ============================================================================ #

# general path additions that aren't big enough to have their own <technology>.sh file

# this is sourced in .bashrc before .bash.d/*.sh because add_PATH() is used extensively everywhere to deduplicate $PATHs across disparate code and also reloads before it gets to this point in the 
Download .txt
gitextract_vlrxn056/

├── .appveyor.yml
├── .bash.d/
│   ├── Makefile
│   ├── README.md
│   ├── aliases.sh
│   ├── android.sh
│   ├── ansible.sh
│   ├── argocd.sh
│   ├── aws-cloudshell.sh
│   ├── aws.sh
│   ├── azure.sh
│   ├── bash_it.sh
│   ├── circleci.sh
│   ├── colors.sh
│   ├── custom.sh
│   ├── direnv.sh
│   ├── docker.sh
│   ├── env.sh
│   ├── functions.sh
│   ├── gcp.sh
│   ├── git.sh
│   ├── golang.sh
│   ├── gpg-agent.sh
│   ├── grype.sh
│   ├── hadoop.sh
│   ├── intellij.sh
│   ├── java.sh
│   ├── jenkins.sh
│   ├── k3d.sh
│   ├── kafka.sh
│   ├── kubernetes.sh
│   ├── linux.sh
│   ├── lolcat.sh
│   ├── mac.sh
│   ├── mercurial.sh
│   ├── mp3.sh
│   ├── mysql.sh
│   ├── network.sh
│   ├── nodejs.sh
│   ├── os_detection.sh
│   ├── paths.sh
│   ├── perl.sh
│   ├── postgres.sh
│   ├── prompt.sh
│   ├── python.sh
│   ├── rancid.sh
│   ├── ruby.sh
│   ├── screen.sh
│   ├── skaffold.sh
│   ├── spinner.sh
│   ├── spotify.sh
│   ├── ssh-agent.sh
│   ├── ssh.sh
│   ├── svn.sh
│   ├── teamcity.sh
│   ├── terraform.sh
│   ├── title.sh
│   ├── travis_ci.sh
│   ├── trivy.sh
│   ├── vagrant.sh
│   ├── vim.sh
│   ├── virtualbox.sh
│   ├── vnc.sh
│   ├── welcome.sh
│   ├── when.sh
│   └── z_final.sh
├── .bash_logout
├── .bash_profile
├── .bashrc
├── .buildkite/
│   └── pipeline.yml
├── .circleci/
│   └── config.yml
├── .cirrus.yml
├── .dockerignore
├── .drone.yml
├── .editorconfig
├── .envrc
├── .envrc-aws
├── .envrc-gcp
├── .envrc-java
├── .envrc-kubernetes
├── .envrc-python
├── .envrc-terraform
├── .git-templates/
│   └── git-secrets/
│       └── hooks/
│           ├── commit-msg
│           ├── pre-commit
│           └── prepare-commit-msg
├── .gitconfig
├── .gitconfig.local
├── .github/
│   ├── CODEOWNERS
│   ├── ISSUE_TEMPLATE.md
│   └── workflows/
│       ├── actions-allowed.txt
│       ├── alpine.yaml
│       ├── alpine_3.yaml
│       ├── centos.yaml.disabled
│       ├── centos7.yaml.disabled
│       ├── centos8.yaml.disabled
│       ├── checkov.yaml
│       ├── codeowners.yaml
│       ├── commit_adjacent_repos.sh
│       ├── debian.yaml
│       ├── debian_10.yaml
│       ├── debian_11.yaml
│       ├── debian_12.yaml
│       ├── debian_6.yaml.disabled
│       ├── debian_7.yaml.disabled
│       ├── debian_8.yaml.disabled
│       ├── debian_9.yaml.disabled
│       ├── docker_bash_alpine.yaml
│       ├── docker_bash_centos.yaml
│       ├── docker_bash_debian.yaml
│       ├── docker_bash_fedora.yaml
│       ├── docker_bash_ubuntu.yaml
│       ├── dockerhub_status_alpine.yaml.disabled
│       ├── dockerhub_status_centos.yaml.disabled
│       ├── dockerhub_status_debian.yaml.disabled
│       ├── dockerhub_status_fedora.yaml.disabled
│       ├── dockerhub_status_ubuntu.yaml.disabled
│       ├── fedora.yaml
│       ├── fork-sync.yaml
│       ├── fork-update-pr.yaml
│       ├── ghcr_bash_ubuntu.yaml.disabled
│       ├── grype.yaml
│       ├── json.yaml
│       ├── kics.yaml
│       ├── mac.yaml
│       ├── mac_11.yaml
│       ├── mac_12.yaml
│       ├── markdown.yaml
│       ├── push_all_repos.sh
│       ├── pypy2.yaml.disabled
│       ├── pypy3.yaml.disabled
│       ├── python2.7.yaml.disabled
│       ├── python3.10.yaml
│       ├── python3.11.yaml
│       ├── python3.6.yaml.disabled
│       ├── python3.7.yaml
│       ├── python3.8.yaml
│       ├── python3.9.yaml
│       ├── self_hosted.yaml.disabled
│       ├── semgrep-cloud.yaml
│       ├── semgrep.yaml
│       ├── shellcheck.yaml
│       ├── sonarcloud.yaml
│       ├── sync_to_adjacent_repos.sh
│       ├── trivy.yaml
│       ├── trivy_image.yaml
│       ├── ubuntu.yaml
│       ├── ubuntu_14.04.yaml.disabled
│       ├── ubuntu_16.04.yaml.disabled
│       ├── ubuntu_18.04.yaml.disabled
│       ├── ubuntu_20.04.yaml
│       ├── ubuntu_22.04.yaml
│       ├── ubuntu_github.yaml
│       ├── url_links.yaml.disabled
│       ├── validate.yaml
│       ├── xml.yaml
│       └── yaml.yaml
├── .gitignore
├── .gitlab-ci.yml
├── .gitmodules
├── .hound.yml
├── .mdl.rb
├── .mdlrc
├── .pre-commit-config.yaml
├── .pylintrc
├── .scrutinizer.yml
├── .semaphore/
│   └── semaphore.yml
├── .sonarcloud.properties
├── .sonarlint/
│   └── connectedMode.json
├── .terraformignore
├── .trivyignore
├── .zlogin
├── .zlogout
├── .zprofile
├── .zshenv
├── .zshrc
├── DOCKER_STATUS.md
├── Gemfile
├── Jenkinsfile
├── LICENSE
├── Makefile
├── Makefile.in
├── README.md
├── STARCHARTS.md
├── STATUS.md
├── ai/
│   └── openai_api.sh
├── applescript/
│   ├── app_names.sh
│   ├── browser_close_tab.scpt
│   ├── browser_get_default.scpt
│   ├── com.harisekhon.wakeup_script.plist
│   ├── get_application_names.scpt
│   ├── get_frontmost_process.scpt
│   ├── get_frontmost_process_title.scpt
│   ├── get_mouse_coordinates.scpt
│   ├── get_mouse_coordinates.sh
│   ├── is_screen_locked.py
│   ├── is_screensaver_running.scpt
│   ├── keystrokes.sh
│   ├── mouse_clicks.scpt
│   ├── mouse_clicks.sh
│   ├── mouse_clicks_remote_desktop.sh
│   ├── mouse_random_movements.sh
│   ├── reopen_app.sh
│   ├── screensaver_activate.scpt
│   ├── set_frontmost_process.scpt
│   ├── set_mic_internal.sh
│   ├── shazam_app_delete_track.sh
│   ├── shazam_app_dump_tracks.sh
│   ├── shazam_search_spotify.sh
│   ├── shazam_search_spotify_then_delete_track.sh
│   ├── shorten_text_selection.scpt
│   ├── spotify_app_search.sh
│   ├── start_app_at_login.sh
│   ├── wakeup_script.sh
│   └── world_clock_cities.txt
├── appveyor/
│   ├── appveyor_api.sh
│   ├── appveyor_byoc.sh
│   ├── appveyor_byoc_debian.sh
│   └── appveyor_delete_offline_byoc.sh
├── aws/
│   ├── .aws_customize_environment
│   ├── aws_account_summary.sh
│   ├── aws_accounts_missing_from_config.sh
│   ├── aws_batch_kill_stale_jobs.sh
│   ├── aws_batch_stale_jobs.sh
│   ├── aws_billing_alarm.sh
│   ├── aws_budget.json
│   ├── aws_budget_alarm.sh
│   ├── aws_budget_notification.json
│   ├── aws_budget_sns_access_policy.json
│   ├── aws_cli_create_credential.sh
│   ├── aws_cloudformation_stacks_pending.sh
│   ├── aws_cloudfront_distribution_for_origin.sh
│   ├── aws_cloudtrails_cloudwatch.sh
│   ├── aws_cloudtrails_event_selectors.sh
│   ├── aws_cloudtrails_s3_accesslogging.sh
│   ├── aws_cloudtrails_s3_kms.sh
│   ├── aws_cloudtrails_status.sh
│   ├── aws_codecommit_csv_creds.sh
│   ├── aws_config_all_types.sh
│   ├── aws_config_recording.sh
│   ├── aws_csv_creds.sh
│   ├── aws_ec2_ami_boot.sh
│   ├── aws_ec2_ami_boot_ssh.sh
│   ├── aws_ec2_ami_create_from_instance.sh
│   ├── aws_ec2_ami_ids.sh
│   ├── aws_ec2_ami_name_to_id.sh
│   ├── aws_ec2_ami_share_to_account.sh
│   ├── aws_ec2_amis.sh
│   ├── aws_ec2_ebs_create_snapshot_and_wait.sh
│   ├── aws_ec2_ebs_resize_and_wait.sh
│   ├── aws_ec2_ebs_volumes.sh
│   ├── aws_ec2_ebs_volumes_unattached.sh
│   ├── aws_ec2_instance_clone.sh
│   ├── aws_ec2_instance_ip.sh
│   ├── aws_ec2_instance_name_to_id.sh
│   ├── aws_ec2_instance_terminate_by_name.sh
│   ├── aws_ec2_instance_wait_for_ready.sh
│   ├── aws_ec2_instances.sh
│   ├── aws_ec2_launch_templates_ami_id.sh
│   ├── aws_ecr_alternate_tags.sh
│   ├── aws_ecr_delete_old_tags.sh
│   ├── aws_ecr_delete_tag.sh
│   ├── aws_ecr_docker_build_push.sh
│   ├── aws_ecr_docker_login.sh
│   ├── aws_ecr_list_repos.sh
│   ├── aws_ecr_list_tags.sh
│   ├── aws_ecr_newest_image_tags.sh
│   ├── aws_ecr_tag_branch.sh
│   ├── aws_ecr_tag_datetime.sh
│   ├── aws_ecr_tag_image.sh
│   ├── aws_ecr_tag_image_by_digest.sh
│   ├── aws_ecr_tag_latest.sh
│   ├── aws_ecr_tag_newest_as_latest.sh
│   ├── aws_ecr_tags_old.sh
│   ├── aws_ecr_tags_timestamps.sh
│   ├── aws_eks_addon_versions.sh
│   ├── aws_eks_ami_create.sh
│   ├── aws_eks_available_ips.sh
│   ├── aws_eks_cloudwatch_logs.sh
│   ├── aws_eks_cluster_versions.sh
│   ├── aws_eks_ssh_dump_logs.sh
│   ├── aws_elasticache_serverless_list.sh
│   ├── aws_emr_clusters_last_steps.sh
│   ├── aws_foreach_profile.sh
│   ├── aws_foreach_region.sh
│   ├── aws_iam_generate_credentials_report_wait.sh
│   ├── aws_iam_harden_password_policy.sh
│   ├── aws_iam_password_policy.sh
│   ├── aws_iam_policies_attached_to_users.sh
│   ├── aws_iam_policies_granting_full_access.sh
│   ├── aws_iam_policies_unattached.sh
│   ├── aws_iam_policy_attachments.sh
│   ├── aws_iam_policy_delete.sh
│   ├── aws_iam_rename_user_accounts_domains.sh
│   ├── aws_iam_replace_access_key.sh
│   ├── aws_iam_users.sh
│   ├── aws_iam_users_access_key_age.sh
│   ├── aws_iam_users_access_key_age_report.sh
│   ├── aws_iam_users_access_key_last_used.sh
│   ├── aws_iam_users_access_key_last_used_report.sh
│   ├── aws_iam_users_last_used_report.sh
│   ├── aws_iam_users_mfa_active_report.sh
│   ├── aws_iam_users_mfa_serials.sh
│   ├── aws_iam_users_pw_last_used.sh
│   ├── aws_iam_users_without_mfa.sh
│   ├── aws_info.sh
│   ├── aws_info_all_profiles.sh
│   ├── aws_info_ec2.sh
│   ├── aws_info_ec2_all_profiles_csv.sh
│   ├── aws_info_ec2_csv.sh
│   ├── aws_ip_ranges.sh
│   ├── aws_kinesis_stream_names.sh
│   ├── aws_kms_key_rotation_enabled.sh
│   ├── aws_kube_creds.sh
│   ├── aws_kubectl.sh
│   ├── aws_logs.sh
│   ├── aws_logs_batch_jobs.sh
│   ├── aws_logs_ec2_spot.sh
│   ├── aws_logs_ecs_tasks.sh
│   ├── aws_meta.sh
│   ├── aws_nat_gateways_public_ips.sh
│   ├── aws_profile.sh
│   ├── aws_profile_config_add_if_missing.sh
│   ├── aws_profile_generate_direnvs.sh
│   ├── aws_rds_get_version.sh
│   ├── aws_rds_list.sh
│   ├── aws_rds_open_port_to_my_ip.sh
│   ├── aws_route53_check_ns_records.sh
│   ├── aws_s3_access_logging.sh
│   ├── aws_s3_account_block_public_access.sh
│   ├── aws_s3_bucket.sh
│   ├── aws_s3_buckets_block_public_access.sh
│   ├── aws_s3_check_account_public_blocked.sh
│   ├── aws_s3_check_buckets_public_blocked.sh
│   ├── aws_s3_delete_bucket_with_versions.sh
│   ├── aws_s3_sync.sh
│   ├── aws_secret_add.sh
│   ├── aws_secret_add_binary.sh
│   ├── aws_secret_get.sh
│   ├── aws_secret_list.sh
│   ├── aws_secret_update.sh
│   ├── aws_secret_update_binary.sh
│   ├── aws_spot_when_terminated.sh
│   ├── aws_sqs_check.sh
│   ├── aws_sqs_delete_messages.sh
│   ├── aws_ssm_put_param.sh
│   ├── aws_ssm_wait_for_command.sh
│   ├── aws_sso_account_id_names.sh
│   ├── aws_sso_accounts.sh
│   ├── aws_sso_accounts_missing_from_list.sh
│   ├── aws_sso_cache_expires.sh
│   ├── aws_sso_config_duplicate_profile_names.sh
│   ├── aws_sso_config_duplicate_sections.sh
│   ├── aws_sso_configs.sh
│   ├── aws_sso_configs_save.sh
│   ├── aws_sso_env_creds.sh
│   ├── aws_sso_role_arn.sh
│   ├── aws_sso_role_arns.sh
│   ├── aws_sso_ssh.sh
│   ├── aws_terraform_create_all.sh
│   ├── aws_terraform_create_atlantis_role.sh
│   ├── aws_terraform_create_credential.sh
│   ├── aws_terraform_create_dynamodb_table.sh
│   ├── aws_terraform_create_s3_bucket.sh
│   ├── aws_terraform_iam_grant_s3_dynamodb.sh
│   └── eksctl_cluster.sh
├── azure-pipelines.yml
├── azure_devops/
│   ├── azure_devops_api.sh
│   ├── azure_devops_disable_repos.sh
│   ├── azure_devops_foreach_repo.sh
│   └── azure_devops_to_github_migration.sh
├── bigdata/
│   ├── beeline.sh
│   ├── beeline_zk.sh
│   ├── cloudera_manager_api.sh
│   ├── cloudera_manager_impala_queries.sh
│   ├── cloudera_manager_impala_queries_ddl.sh
│   ├── cloudera_manager_impala_queries_exceptions.sh
│   ├── cloudera_manager_impala_queries_failed.sh
│   ├── cloudera_manager_impala_queries_metadata.sh
│   ├── cloudera_manager_impala_queries_metadata_errors.sh
│   ├── cloudera_manager_impala_queries_metadata_refresh.sh
│   ├── cloudera_manager_yarn_apps.sh
│   ├── cloudera_manager_yarn_apps_failed.sh
│   ├── cloudera_navigator_api.sh
│   ├── cloudera_navigator_audit_logs.sh
│   ├── cloudera_navigator_audit_logs_download.sh
│   ├── cloudera_navigator_audit_logs_download_retry.sh
│   ├── cloudera_navigator_audit_logs_export_postgresql.sh
│   ├── hadoop_random_node.sh
│   ├── hdfs_checksum.sh
│   ├── hdfs_checksum_crc.sh
│   ├── hdfs_checksum_crc_parallel.sh
│   ├── hdfs_checksum_parallel.sh
│   ├── hdfs_file_size.sh
│   ├── hdfs_file_size_including_replicas.sh
│   ├── hdfs_find_replication_factor_1.sh
│   ├── hdfs_set_replication_factor_3.sh
│   ├── hive_foreach_table.sh
│   ├── hive_list_databases.sh
│   ├── hive_list_tables.sh
│   ├── hive_tables_column_counts.sh
│   ├── hive_tables_locations.sh
│   ├── hive_tables_metadata.sh
│   ├── hive_tables_row_counts.sh
│   ├── impala_foreach_table.sh
│   ├── impala_list_databases.sh
│   ├── impala_list_tables.sh
│   ├── impala_shell.sh
│   ├── impala_tables_column_counts.sh
│   ├── impala_tables_locations.sh
│   ├── impala_tables_metadata.sh
│   ├── impala_tables_row_counts.sh
│   ├── zookeeper_client.sh
│   └── zookeeper_shell.sh
├── bin/
│   ├── bash_most_used_commands.sh
│   ├── bash_profile_bashrc.sh
│   ├── center.sh
│   ├── clean_caches.sh
│   ├── cocomo_man_years_estimate.sh
│   ├── copy_to_clipboard.sh
│   ├── crt_hash.sh
│   ├── crypto_dice_rolls.sh
│   ├── curl_auth.sh
│   ├── curl_with_cookies.sh
│   ├── debian_netinstall_pxesetup.sh
│   ├── decomment.sh
│   ├── delete_duplicate_files.sh
│   ├── delete_empty_dirs.sh
│   ├── diff_line_threshold.sh
│   ├── disable_swap.sh
│   ├── disk-read-random.fio
│   ├── disk-read-sequential.fio
│   ├── disk-tests.fio
│   ├── disk-write-random.fio
│   ├── disk-write-sequential.fio
│   ├── disk_speed_read_random_dd.sh
│   ├── disk_speed_read_random_fio.sh
│   ├── disk_speed_read_sequential_dd.sh
│   ├── disk_speed_read_sequential_fio.sh
│   ├── disk_speed_write_random_fio.sh
│   ├── disk_speed_write_sequential_dd.sh
│   ├── disk_speed_write_sequential_fio.sh
│   ├── download_url_file.sh
│   ├── elasticsearch_decommission_node.sh
│   ├── exec_interactive.sh
│   ├── file_extensions.sh
│   ├── find_broken_links.sh
│   ├── find_broken_symlinks.sh
│   ├── find_duplicate_files_by_checksum.sh
│   ├── find_duplicate_files_by_size.sh
│   ├── find_duplicate_lines.sh
│   ├── find_hanging_mount_point.sh
│   ├── find_hardlinks.sh
│   ├── find_lock.sh
│   ├── find_symlinks_to_other_directories.sh
│   ├── foreach_path_bin.sh
│   ├── grep_or_append.sh
│   ├── hackercase.sh
│   ├── headtail.sh
│   ├── hexencode.sh
│   ├── htmldecode.sh
│   ├── http_duplicate_urls.sh
│   ├── jsondiff.sh
│   ├── keycloak.sh
│   ├── ldap_group_recurse.sh
│   ├── ldap_user_recurse.sh
│   ├── ldapsearch.sh
│   ├── lint.sh
│   ├── linux_distro_versions.sh
│   ├── login.sh
│   ├── lowercase_filename.sh
│   ├── mac_backup_du_in_progress.sh
│   ├── mac_backup_exclude_paths.sh
│   ├── mac_backup_find_excluded_paths.sh
│   ├── mac_delete_local_snapshots.sh
│   ├── mac_diff_settings.sh
│   ├── mac_gif_preview.sh
│   ├── mac_iso_to_usb.sh
│   ├── mac_ramdisk.sh
│   ├── mac_restore_file.sh
│   ├── mac_rmdir.sh
│   ├── mv.sh
│   ├── network_gateway.sh
│   ├── open.sh
│   ├── oreilly_cover_download.sh
│   ├── organize_downloads.sh
│   ├── paste_diff_settings.sh
│   ├── paste_from_clipboard.sh
│   ├── paste_from_clipboard_upon_changes.sh
│   ├── path_revoke_world_writeable.sh
│   ├── pldd.sh
│   ├── processes_ram_sum.sh
│   ├── progress_dots.sh
│   ├── random_number.sh
│   ├── random_select.sh
│   ├── random_string.sh
│   ├── retry.sh
│   ├── run.sh
│   ├── sbtw
│   ├── scan_duplicate_macs.sh
│   ├── screen_terminal_to_clipboard.sh
│   ├── screen_terminal_to_stdout.sh
│   ├── shorten_text_selection.sh
│   ├── shred_file.sh
│   ├── shred_free_space.sh
│   ├── smart_quotes_replace.sh
│   ├── spasticcase.sh
│   ├── spasticcase2.sh
│   ├── split.sh
│   ├── sqlite.sh
│   ├── ssl_get_cert.sh
│   ├── ssl_verify_cert.sh
│   ├── ssl_verify_cert_by_ip.sh
│   ├── ssl_view_cert.sh
│   ├── text_filter_ending_substrings.sh
│   ├── tmux_horizontal.sh
│   ├── tmux_square.sh
│   ├── tmux_vertical.sh
│   ├── ubuntu_release_version.sh
│   ├── uniq_chars.sh
│   ├── url_extract_redirects.sh
│   ├── url_replace_redirects.sh
│   ├── urldecode.sh
│   ├── urlencode.sh
│   ├── urlencode_utf.sh
│   ├── urlextract.sh
│   ├── urlopen.sh
│   └── vault_pass.sh
├── bitbucket/
│   ├── bitbucket_api.sh
│   ├── bitbucket_disable_pipelines.sh
│   ├── bitbucket_enable_pipelines.sh
│   ├── bitbucket_foreach_repo.sh
│   ├── bitbucket_repo_disable_pipeline.sh
│   ├── bitbucket_repo_enable_pipeline.sh
│   ├── bitbucket_repo_set_description.sh
│   ├── bitbucket_repo_set_env_vars.sh
│   ├── bitbucket_ssh_add_public_keys.sh
│   ├── bitbucket_ssh_delete_public_keys.sh
│   ├── bitbucket_ssh_get_public_keys.sh
│   └── bitbucket_workspace_set_env_vars.sh
├── bitbucket-pipelines.yml
├── buddy.yml
├── buildkite/
│   ├── buildkite_agent.sh
│   ├── buildkite_agents.sh
│   ├── buildkite_api.sh
│   ├── buildkite_cancel_running_builds.sh
│   ├── buildkite_cancel_scheduled_builds.sh
│   ├── buildkite_create_pipeline.sh
│   ├── buildkite_foreach_pipeline.sh
│   ├── buildkite_get_pipeline.sh
│   ├── buildkite_patch_pipeline.sh
│   ├── buildkite_pipeline_disable_forked_pull_requests.sh
│   ├── buildkite_pipeline_set_skip_settings.sh
│   ├── buildkite_pipeline_skip_settings.sh
│   ├── buildkite_pipelines.sh
│   ├── buildkite_pipelines_vulnerable_forked_pull_requests.sh
│   ├── buildkite_rebuild_all_pipelines_last_cancelled.sh
│   ├── buildkite_rebuild_all_pipelines_last_failed.sh
│   ├── buildkite_rebuild_cancelled_builds.sh
│   ├── buildkite_rebuild_failed_builds.sh
│   ├── buildkite_rebuild_last_cancelled.sh
│   ├── buildkite_recreate_pipeline.sh
│   ├── buildkite_retry_jobs_dead_agents.sh
│   ├── buildkite_running_builds.sh
│   ├── buildkite_save_pipelines.sh
│   ├── buildkite_set_pipeline_description.sh
│   ├── buildkite_set_pipeline_description_from_github.sh
│   ├── buildkite_sync_pipeline_descriptions_from_github.sh
│   ├── buildkite_trigger.sh
│   ├── buildkite_trigger_all.sh
│   └── buildkite_update_pipeline.sh
├── checks/
│   ├── check_all.sh
│   ├── check_ansible_playbooks.sh
│   ├── check_aws_no_git_credentials.sh
│   ├── check_bash_arrays.sh
│   ├── check_bash_duplicate_defs.sh
│   ├── check_bash_references.sh
│   ├── check_bash_syntax.sh
│   ├── check_caches_clean.sh
│   ├── check_circleci_config.sh
│   ├── check_codefresh_config.sh
│   ├── check_concourse_config.sh
│   ├── check_cson.sh
│   ├── check_docker_clean.sh
│   ├── check_docker_compose.sh
│   ├── check_dockerfiles.sh
│   ├── check_drone_yml.sh
│   ├── check_duplicate_dependencies.sh
│   ├── check_duplicate_packages.sh
│   ├── check_git_commit_authors.sh
│   ├── check_git_no_merge_remnants.sh
│   ├── check_github_actions_workflow_injection.sh
│   ├── check_github_actions_workflows_without_checkout.sh
│   ├── check_github_codeowners.sh
│   ├── check_gitlab_ci_yml.sh
│   ├── check_gradle_build.sh
│   ├── check_groovyc.sh
│   ├── check_internet.sh
│   ├── check_javac.sh
│   ├── check_javascript_eslint.sh
│   ├── check_jenkinsfiles.sh
│   ├── check_json.sh
│   ├── check_kubernetes_yaml.sh
│   ├── check_license_exists.sh
│   ├── check_makefiles.sh
│   ├── check_maven_pom.sh
│   ├── check_no_suid_guid_shell_scripts.sh
│   ├── check_no_tabs.sh
│   ├── check_perl_syntax.sh
│   ├── check_python3_compat.sh
│   ├── check_python_asserts.sh
│   ├── check_python_exception_pass.sh
│   ├── check_python_misc.sh
│   ├── check_python_pep8.sh
│   ├── check_python_pylint.sh
│   ├── check_pytools.sh
│   ├── check_readme_badges.sh
│   ├── check_readme_exists.sh
│   ├── check_ruby_syntax.sh
│   ├── check_sbt_build.sh
│   ├── check_shebang_non_executable.sh
│   ├── check_shell_commands_dash_protections.sh
│   ├── check_shellcheck.sh
│   ├── check_shippable_readme_ids.sh
│   ├── check_sqlfluff.sh
│   ├── check_srcdir_references.sh
│   ├── check_ssh_keys_encrypted.sh
│   ├── check_symlinks.sh
│   ├── check_tests_run_qualified.sh
│   ├── check_tld_chars.sh
│   ├── check_travis_yml.sh
│   ├── check_url_links.sh
│   ├── check_vagrantfiles.sh
│   ├── check_whitespace.sh
│   ├── check_xml.sh
│   └── check_yaml.sh
├── cicd/
│   ├── .concourse.yml
│   ├── .gocd.yml
│   ├── buildspec.yml
│   ├── checkov_resource_count.sh
│   ├── checkov_resource_count_all.sh
│   ├── cloudbuild.yaml
│   ├── codefresh_cancel_delayed_builds.sh
│   ├── concourse.sh
│   ├── coveralls_latest.sh
│   ├── fly.sh
│   ├── generate_status_page.sh
│   ├── gerrit.sh
│   ├── gerrit_projects.sh
│   ├── gocd.sh
│   ├── gocd_api.sh
│   ├── octopus_api.sh
│   ├── run_latest_tests.sh
│   ├── run_tests.sh
│   ├── selenium_hub_wait_ready.sh
│   ├── sonarlint_generate_config.sh
│   ├── sync_bootstraps_to_adjacent_repos.sh
│   ├── sync_ci_to_adjacent_repos.sh
│   ├── sync_configs_to_adjacent_repos.sh
│   └── sync_github_actions_workflows_to_adjacent_repos.sh
├── circleci/
│   ├── circleci_api.sh
│   ├── circleci_context_delete_env_vars.sh
│   ├── circleci_context_set_env_vars.sh
│   ├── circleci_local_execute.sh
│   ├── circleci_project_delete_env_vars.sh
│   ├── circleci_project_set_env_vars.sh
│   └── circleci_public_ips.sh
├── cloudflare/
│   ├── cloudflare_api.sh
│   ├── cloudflare_custom_certificates.sh
│   ├── cloudflare_dns_record_create.sh
│   ├── cloudflare_dns_record_delete.sh
│   ├── cloudflare_dns_record_details.sh
│   ├── cloudflare_dns_record_update.sh
│   ├── cloudflare_dns_records.sh
│   ├── cloudflare_dns_records_all_zones.sh
│   ├── cloudflare_dnssec.sh
│   ├── cloudflare_firewall_access_rules.sh
│   ├── cloudflare_firewall_rules.sh
│   ├── cloudflare_foreach_account.sh
│   ├── cloudflare_foreach_zone.sh
│   ├── cloudflare_ip_ranges.sh
│   ├── cloudflare_purge_cache.sh
│   ├── cloudflare_ssl_verified.sh
│   ├── cloudflare_ssl_verified_all_zones.sh
│   └── cloudflare_zones.sh
├── codefresh.yml
├── codeship/
│   ├── codeship.yml
│   ├── codeship_api.sh
│   └── codeship_api_token.sh
├── configs/
│   ├── .Codefresh/
│   │   └── cli-config/
│   │       └── config.yaml
│   ├── .Xdefaults
│   ├── .Xmodmap
│   ├── .ansible.cfg
│   ├── .athenacli/
│   │   └── athenaclirc
│   ├── .aws/
│   │   ├── config
│   │   └── shell/
│   │       └── awsshellrc
│   ├── .checkov.yaml
│   ├── .config/
│   │   ├── flake8
│   │   ├── htop/
│   │   │   └── htoprc
│   │   ├── pycodestyle
│   │   ├── terminalizer/
│   │   │   └── config.yml
│   │   └── yamllint/
│   │       └── config
│   ├── .gemrc
│   ├── .grype.yaml
│   ├── .inputrc
│   ├── .luacheckrc
│   ├── .my.cnf
│   ├── .perlcritic_forbidden_modules
│   ├── .perlcriticrc
│   ├── .psqlrc
│   ├── .sawsrc
│   ├── .screenrc
│   ├── .sdkman/
│   │   └── etc/
│   │       └── config
│   ├── .sqliterc
│   ├── .terraformrc
│   ├── .tfdocs.d/
│   │   └── .terraform-docs.yml
│   ├── .tmux.conf
│   ├── .toprc
│   ├── .vimrc
│   ├── .wakatime.cfg
│   ├── .yamllint.yaml
│   ├── README.md
│   ├── clamd.conf
│   └── freshclam.conf
├── data/
│   ├── avro_tools.sh
│   ├── csv_header_indices.sh
│   ├── ini_config_add_if_missing.sh
│   ├── ini_config_duplicate_section_names.sh
│   ├── ini_config_duplicate_sections.sh
│   ├── ini_grep_section.sh
│   ├── json2yaml.sh
│   ├── lines_to_end.sh
│   ├── parquet_tools.sh
│   ├── wordcloud.sh
│   ├── wordcount.sh
│   └── yaml2json.sh
├── diagrams/
│   ├── d2.sh
│   ├── d2_generate_diagrams.sh
│   ├── mermaidjs_generate_diagrams.sh
│   └── python_mingrammer_generate_diagrams.sh
├── docker/
│   ├── docker_api.sh
│   ├── docker_build_hashref.sh
│   ├── docker_generate_status_page.sh
│   ├── docker_mount_build_exec.sh
│   ├── docker_package_check.sh
│   ├── docker_registry_get_image_manifest.sh
│   ├── docker_registry_list_images.sh
│   ├── docker_registry_list_tags.sh
│   ├── docker_registry_tag_image.sh
│   ├── dockerhub_api.sh
│   ├── dockerhub_build_status.sh
│   ├── dockerhub_list_tags.sh
│   ├── dockerhub_list_tags_by_last_updated.sh
│   ├── dockerhub_repo_set_description.sh
│   ├── dockerhub_repo_set_readme.sh
│   ├── dockerhub_search.sh
│   └── quay_api.sh
├── docker-compose/
│   ├── circleci.yml
│   ├── concourse.yml
│   ├── gerrit.yml
│   ├── gocd.yml
│   ├── jenkins.yml
│   ├── keycloak.yml
│   ├── octopus-deploy.env
│   ├── octopus-deploy.yml
│   ├── prometheus.yml
│   ├── teamcity.yml
│   └── wordpress.yml
├── drone/
│   ├── drone_api.sh
│   ├── drone_docker_runner.sh
│   └── drone_docker_server.sh
├── gcp/
│   ├── .customize_environment
│   ├── .gcloudignore
│   ├── bigquery_foreach_dataset.sh
│   ├── bigquery_foreach_table.sh
│   ├── bigquery_foreach_table_all_datasets.sh
│   ├── bigquery_generate_query_biggest_tables_across_datasets_by_row_count.sh
│   ├── bigquery_generate_query_biggest_tables_across_datasets_by_size.sh
│   ├── bigquery_list_datasets.sh
│   ├── bigquery_list_tables.sh
│   ├── bigquery_list_tables_all_datasets.sh
│   ├── bigquery_table_row_count.sh
│   ├── bigquery_tables_row_counts.sh
│   ├── bigquery_tables_row_counts_all_datasets.sh
│   ├── firebase_foreach_project.sh
│   ├── gce_foreach_vm.sh
│   ├── gce_host_ips.sh
│   ├── gce_instance_service_accounts.sh
│   ├── gce_is_preempted.sh
│   ├── gce_meta.sh
│   ├── gce_ssh.sh
│   ├── gce_ssh_keyscan.sh
│   ├── gce_when_preempted.sh
│   ├── gcp_ansible_create_credential.sh
│   ├── gcp_ci_build.sh
│   ├── gcp_ci_deploy_k8s.sh
│   ├── gcp_cli_create_credential.sh
│   ├── gcp_cloud_schedule_sql_exports.sh
│   ├── gcp_find_orphaned_disks.sh
│   ├── gcp_firewall_disable_default_rules.sh
│   ├── gcp_firewall_risky_rules.sh
│   ├── gcp_foreach_project.sh
│   ├── gcp_iam_identities_in_use.sh
│   ├── gcp_iam_roles_granted_to_identity.sh
│   ├── gcp_iam_roles_granted_too_widely.sh
│   ├── gcp_iam_roles_in_use.sh
│   ├── gcp_iam_roles_with_direct_user_grants.sh
│   ├── gcp_iam_serviceaccount_members.sh
│   ├── gcp_iam_serviceaccounts_without_permissions.sh
│   ├── gcp_iam_users_granted_directly.sh
│   ├── gcp_iam_workload_identities.sh
│   ├── gcp_info.sh
│   ├── gcp_info_accounts_secrets.sh
│   ├── gcp_info_all_projects.sh
│   ├── gcp_info_auth_config.sh
│   ├── gcp_info_bigdata.sh
│   ├── gcp_info_cloud_sql.sh
│   ├── gcp_info_cloud_sql_backups.sh
│   ├── gcp_info_cloud_sql_databases.sh
│   ├── gcp_info_cloud_sql_users.sh
│   ├── gcp_info_compute.sh
│   ├── gcp_info_gke.sh
│   ├── gcp_info_networking.sh
│   ├── gcp_info_projects.sh
│   ├── gcp_info_services.sh
│   ├── gcp_info_storage.sh
│   ├── gcp_info_tools.sh
│   ├── gcp_secret_add.sh
│   ├── gcp_secret_add_binary.sh
│   ├── gcp_secret_get.sh
│   ├── gcp_secret_label_k8s.sh
│   ├── gcp_secret_update.sh
│   ├── gcp_secrets_labels.sh
│   ├── gcp_secrets_to_kubernetes.sh
│   ├── gcp_secrets_to_kubernetes_multipart.sh
│   ├── gcp_secrets_update_label.sh
│   ├── gcp_service_account_credential_to_secret.sh
│   ├── gcp_service_account_members.sh
│   ├── gcp_service_accounts_credential_keys.sh
│   ├── gcp_service_accounts_credential_keys_age.sh
│   ├── gcp_service_accounts_credential_keys_expired.sh
│   ├── gcp_service_apis.sh
│   ├── gcp_spinnaker_create_credential.sh
│   ├── gcp_sql_backup.sh
│   ├── gcp_sql_create_readonly_service_account.sh
│   ├── gcp_sql_enable_automated_backups.sh
│   ├── gcp_sql_enable_point_in_time_recovery.sh
│   ├── gcp_sql_export.sh
│   ├── gcp_sql_grant_instances_gcs_object_creator.sh
│   ├── gcp_sql_list_databases.sh
│   ├── gcp_sql_proxy.sh
│   ├── gcp_sql_running_primaries.sh
│   ├── gcp_sql_service_accounts.sh
│   ├── gcp_terraform_create_credential.sh
│   ├── gcr_alternate_tags.sh
│   ├── gcr_delete_old_tags.sh
│   ├── gcr_list_tags.sh
│   ├── gcr_newest_image_tags.sh
│   ├── gcr_tag_branch.sh
│   ├── gcr_tag_datetime.sh
│   ├── gcr_tag_latest.sh
│   ├── gcr_tag_newest_image_as_latest.sh
│   ├── gcr_tags_old.sh
│   ├── gcr_tags_timestamps.sh
│   ├── gcs_bucket_project.sh
│   ├── gcs_curl_file.sh
│   ├── gke_firewall_rule_cert_manager.sh
│   ├── gke_firewall_rule_kubeseal.sh
│   ├── gke_kube_creds.sh
│   ├── gke_kubectl.sh
│   ├── gke_nodepool_drain.sh
│   ├── gke_nodepool_nodes.sh
│   ├── gke_nodepool_nodes2.sh
│   ├── gke_nodepool_taint.sh
│   └── gke_persistent_volume_disk_mappings.sh
├── git/
│   ├── git_askpass.sh
│   ├── git_branch_delete_squash_merged.sh
│   ├── git_clean_repos.sh
│   ├── git_diff_commit.sh
│   ├── git_files_in_history.sh
│   ├── git_files_last_modified.sh
│   ├── git_files_no_uncommitted_changes.sh
│   ├── git_filter_branch_fix_author.sh
│   ├── git_filter_repo_replace_text.sh
│   ├── git_foreach_branch.sh
│   ├── git_foreach_modified.sh
│   ├── git_foreach_repo.sh
│   ├── git_foreach_repo_replace_readme_actions.sh
│   ├── git_foreach_repo_update_readme.sh
│   ├── git_graph_commit_history_gnuplot.sh
│   ├── git_graph_commit_history_mermaidjs.sh
│   ├── git_graph_commit_times_gnuplot.sh
│   ├── git_graph_commit_times_gnuplot_all_repos.sh
│   ├── git_graph_commit_times_mermaidjs.sh
│   ├── git_graph_commit_times_mermaidjs_all_repos.sh
│   ├── git_grep_env_vars.sh
│   ├── git_log_empty_commits.sh
│   ├── git_log_me.sh
│   ├── git_log_me_added.sh
│   ├── git_merge_all.sh
│   ├── git_merge_branch.sh
│   ├── git_merge_master.sh
│   ├── git_merge_master_pull.sh
│   ├── git_origin_commit_count_to_push.sh
│   ├── git_origin_diff_to_push.sh
│   ├── git_origin_files_to_push.sh
│   ├── git_origin_line_count_to_push.sh
│   ├── git_origin_log_to_push.sh
│   ├── git_pull_make_repos.sh
│   ├── git_push_stats.sh
│   ├── git_remotes_add_origin_providers.sh
│   ├── git_remotes_set_https_creds_helpers.sh
│   ├── git_remotes_set_https_to_ssh.sh
│   ├── git_remotes_set_multi_origin.sh
│   ├── git_remotes_set_ssh_to_https.sh
│   ├── git_repos.sh
│   ├── git_repos_pull.sh
│   ├── git_repos_update.sh
│   ├── git_revert_line.sh
│   ├── git_review_push.sh
│   ├── git_set_dir_safe.sh
│   ├── git_submodules_update.sh
│   ├── git_submodules_update_repos.sh
│   ├── git_summary_line.sh
│   ├── git_sync_repos_upstream.sh
│   ├── git_tag_release.sh
│   ├── gitguardian_api.sh
│   ├── gitignore.io_api.sh
│   ├── precommit_run_changed_files.sh
│   └── update_gitignore.io.sh
├── github/
│   ├── github_actions_aws_create_load_credential.sh
│   ├── github_actions_delete_offline_runners.sh
│   ├── github_actions_foreach_workflow.sh
│   ├── github_actions_in_use.sh
│   ├── github_actions_in_use_across_repos.sh
│   ├── github_actions_in_use_repo.sh
│   ├── github_actions_latest_log.sh
│   ├── github_actions_log.sh
│   ├── github_actions_repo_actions_allow.sh
│   ├── github_actions_repo_env_set_secret.sh
│   ├── github_actions_repo_restrict_actions.sh
│   ├── github_actions_repo_secrets_overriding_org.sh
│   ├── github_actions_repo_set_secret.sh
│   ├── github_actions_repos_lockdown.sh
│   ├── github_actions_runner.sh
│   ├── github_actions_runner_local.sh
│   ├── github_actions_runner_token.sh
│   ├── github_actions_runners.sh
│   ├── github_actions_workflow_enable.sh
│   ├── github_actions_workflow_runs.sh
│   ├── github_actions_workflows.sh
│   ├── github_actions_workflows_cancel_all_runs.sh
│   ├── github_actions_workflows_cancel_waiting_runs.sh
│   ├── github_actions_workflows_disabled.sh
│   ├── github_actions_workflows_enable_all.sh
│   ├── github_actions_workflows_rerun_failed.sh
│   ├── github_actions_workflows_state.sh
│   ├── github_actions_workflows_status.sh
│   ├── github_actions_workflows_status2.sh
│   ├── github_actions_workflows_trigger_all.sh
│   ├── github_api.sh
│   ├── github_clone_or_pull_all_repos.sh
│   ├── github_download_release_file.sh
│   ├── github_download_release_jar.sh
│   ├── github_foreach_repo.sh
│   ├── github_forked_add_remote.sh
│   ├── github_forked_checkout_branch.sh
│   ├── github_generate_starcharts.md.sh
│   ├── github_generate_status_page.sh
│   ├── github_gpg_get_user_keys.sh
│   ├── github_graph_commit_times_gnuplot.sh
│   ├── github_graph_commit_times_mermaidjs.sh
│   ├── github_install_binary.sh
│   ├── github_invitations.sh
│   ├── github_ip_ranges.sh
│   ├── github_merge_branch.sh
│   ├── github_mirror_repos_to_aws_codecommit.sh
│   ├── github_mirror_repos_to_bitbucket.sh
│   ├── github_mirror_repos_to_gcp_source_repos.sh
│   ├── github_mirror_repos_to_gitlab.sh
│   ├── github_public_lines_of_code.sh
│   ├── github_pull_merge_trunk.sh
│   ├── github_pull_request_create.sh
│   ├── github_pull_request_preview.sh
│   ├── github_purge_camo_cache.sh
│   ├── github_push_pr.sh
│   ├── github_push_pr_preview.sh
│   ├── github_release.sh
│   ├── github_remote_set_upstream.sh
│   ├── github_repo_add_collaborator.sh
│   ├── github_repo_check_pat_token.sh
│   ├── github_repo_collaborators.sh
│   ├── github_repo_description.sh
│   ├── github_repo_find_files.sh
│   ├── github_repo_fork_sync.sh
│   ├── github_repo_fork_update.sh
│   ├── github_repo_latest_release.sh
│   ├── github_repo_latest_release_filter.sh
│   ├── github_repo_protect_branches.sh
│   ├── github_repo_stars.sh
│   ├── github_repo_teams.sh
│   ├── github_repos_disable_rebase.sh
│   ├── github_repos_disable_wiki.sh
│   ├── github_repos_find_files.sh
│   ├── github_repos_not_in_terraform.sh
│   ├── github_repos_public.sh
│   ├── github_repos_sync_status.sh
│   ├── github_repos_with_few_teams.sh
│   ├── github_repos_with_few_users.sh
│   ├── github_repos_without_branch_protections.sh
│   ├── github_ssh_add_public_keys.sh
│   ├── github_ssh_delete_public_keys.sh
│   ├── github_ssh_get_public_keys.sh
│   ├── github_ssh_get_user_public_keys.sh
│   ├── github_ssh_get_user_public_keys2.sh
│   ├── github_sync_repo_descriptions.sh
│   ├── github_tag_hashref.sh
│   ├── github_teams_not_idp_synced.sh
│   ├── github_teams_not_in_terraform.sh
│   ├── github_url_clipboard.sh
│   ├── github_user_followers.sh
│   ├── github_user_repos_count.sh
│   ├── github_user_repos_forks.sh
│   ├── github_user_repos_stars.sh
│   └── gitio.sh
├── gitlab/
│   ├── gitlab_api.sh
│   ├── gitlab_foreach_repo.sh
│   ├── gitlab_get_user_ssh_public_keys.sh
│   ├── gitlab_get_user_ssh_public_keys2.sh
│   ├── gitlab_group_set_env_vars.sh
│   ├── gitlab_install_binary.sh
│   ├── gitlab_project_create_import.sh
│   ├── gitlab_project_latest_release.sh
│   ├── gitlab_project_mirrors.sh
│   ├── gitlab_project_protect_branches.sh
│   ├── gitlab_project_set_description.sh
│   ├── gitlab_project_set_env_vars.sh
│   ├── gitlab_pull_mirror.sh
│   ├── gitlab_push_mr.sh
│   ├── gitlab_push_mr_preview.sh
│   ├── gitlab_ssh_add_public_keys.sh
│   ├── gitlab_ssh_delete_public_keys.sh
│   ├── gitlab_ssh_get_public_keys.sh
│   └── gitlab_validate_ci_yaml.sh
├── hadolint.yaml
├── images/
│   └── README.md
├── install/
│   ├── download_avro_tools.sh
│   ├── download_azul_openjdk.sh
│   ├── download_bytecode_viewer_jar.sh
│   ├── download_cfr_jar.sh
│   ├── download_jd_gui_jar.sh
│   ├── download_mssql_jdbc_jar.sh
│   ├── download_mysql_jdbc_jar.sh
│   ├── download_openjdk.sh
│   ├── download_parquet_tools.sh
│   ├── download_postgres_jdbc_jar.sh
│   ├── download_procyon_jar.sh
│   ├── download_vertica_jar.sh
│   ├── getawless.sh
│   ├── install_android_commandlinetools.sh
│   ├── install_android_sdk.sh
│   ├── install_ansible.sh
│   ├── install_appveyor_byoc.sh
│   ├── install_argocd.sh
│   ├── install_awless.sh
│   ├── install_aws_cli.sh
│   ├── install_aws_ebcli.sh
│   ├── install_aws_sam_cli.sh
│   ├── install_azure_cli.sh
│   ├── install_azure_devops_cli.sh
│   ├── install_bazel.sh
│   ├── install_bazelisk.sh
│   ├── install_buildkite.sh
│   ├── install_cert_manager_cli.sh
│   ├── install_circleci.sh
│   ├── install_circleci_runner.sh
│   ├── install_clairctl.sh
│   ├── install_cliclick.sh
│   ├── install_cloud_sql_proxy.sh
│   ├── install_cloudbees.sh
│   ├── install_coder_cli.sh
│   ├── install_container-diff.sh
│   ├── install_crictl.sh
│   ├── install_d2.sh
│   ├── install_datree.sh
│   ├── install_diff-so-fancy.sh
│   ├── install_direnv.sh
│   ├── install_docker_buildx.sh
│   ├── install_docker_compose.sh
│   ├── install_docker_scan.sh
│   ├── install_dockerhub_cli.sh
│   ├── install_dockle.sh
│   ├── install_doctl.sh
│   ├── install_drone.sh
│   ├── install_eksctl.sh
│   ├── install_eksup.sh
│   ├── install_epel_repo.sh
│   ├── install_etcd.sh
│   ├── install_firebase_cli.sh
│   ├── install_fly.sh
│   ├── install_fossa_cli.sh
│   ├── install_gcloud_sdk.sh
│   ├── install_github_cli.sh
│   ├── install_github_codeql.sh
│   ├── install_github_ssh_keys.sh
│   ├── install_gitlab_cli.sh
│   ├── install_golang.sh
│   ├── install_gonogo.sh
│   ├── install_gradle.sh
│   ├── install_groovy.sh
│   ├── install_grype.sh
│   ├── install_helm.sh
│   ├── install_homebrew.sh
│   ├── install_infoblox_ova.sh
│   ├── install_intellij_plugins.sh
│   ├── install_java.sh
│   ├── install_jfrog_cli.sh
│   ├── install_jx.sh
│   ├── install_k3d.sh
│   ├── install_k3s.sh
│   ├── install_k6.sh
│   ├── install_keeper_cli.sh
│   ├── install_kics.sh
│   ├── install_kind.sh
│   ├── install_knative_cli.sh
│   ├── install_kops.sh
│   ├── install_kubectl.sh
│   ├── install_kubectl_plugin_cert_manager.sh
│   ├── install_kubectl_plugin_convert.sh
│   ├── install_kubectl_plugin_krew.sh
│   ├── install_kubent.sh
│   ├── install_kubescape.sh
│   ├── install_kubeseal.sh
│   ├── install_kubevious.sh
│   ├── install_kustomize.sh
│   ├── install_maven.sh
│   ├── install_mermaidjs.sh
│   ├── install_minikube.sh
│   ├── install_minishift.sh
│   ├── install_mousetools.sh
│   ├── install_ngrok.sh
│   ├── install_nova.sh
│   ├── install_octo.sh
│   ├── install_oh-my-zsh.sh
│   ├── install_openssh.sh
│   ├── install_oracle_client.sh
│   ├── install_oracle_sql_developer.sh
│   ├── install_oracle_sqlcl.sh
│   ├── install_packer.sh
│   ├── install_parquet-tools.sh
│   ├── install_pluto.sh
│   ├── install_polaris.sh
│   ├── install_powershell.sh
│   ├── install_powershell_debian.sh
│   ├── install_powershell_rhel.sh
│   ├── install_powershell_ubuntu.sh
│   ├── install_prometheus.sh
│   ├── install_prometheus_alertmanager.sh
│   ├── install_prometheus_blackbox_exporter.sh
│   ├── install_prometheus_consul_exporter.sh
│   ├── install_prometheus_graphite_exporter.sh
│   ├── install_prometheus_memcached_exporter.sh
│   ├── install_prometheus_mysqld_exporter.sh
│   ├── install_prometheus_node_exporter.sh
│   ├── install_prometheus_push_gateway.sh
│   ├── install_prometheus_statsd_exporter.sh
│   ├── install_promlens.sh
│   ├── install_pulumi_cli.sh
│   ├── install_rancher_cli.sh
│   ├── install_rpmforge.sh
│   ├── install_rvm.sh
│   ├── install_sbt.sh
│   ├── install_sdkman.sh
│   ├── install_sdkman_all_sdks.sh
│   ├── install_semaphore_ci.sh
│   ├── install_serverless.sh
│   ├── install_spotifycontrol.sh
│   ├── install_squirrel_sql.sh
│   ├── install_syft.sh
│   ├── install_talosctl.sh
│   ├── install_terraform.sh
│   ├── install_terraformer.sh
│   ├── install_terragrunt.sh
│   ├── install_tfenv.sh
│   ├── install_tfsec.sh
│   ├── install_tgswitch.sh
│   ├── install_tkn.sh
│   ├── install_travis.sh
│   ├── install_trivy.sh
│   ├── install_vertica_vsql_client.sh
│   ├── install_vertica_vsql_client_rpm.sh
│   ├── install_vundle.sh
│   ├── install_wercker_cli.sh
│   └── install_yq.sh
├── internet/
│   ├── 0x0.sh
│   ├── atlassian_ip_ranges.sh
│   ├── catbox.sh
│   ├── datadog_api.sh
│   ├── digital_ocean_api.sh
│   ├── dnsjson.sh
│   ├── domains_subdomains_environments.sh
│   ├── dpaste.sh
│   ├── file.io.sh
│   ├── google_maps_link.sh
│   ├── imgur.sh
│   ├── jira_api.sh
│   ├── kong_api.sh
│   ├── litterbox.sh
│   ├── ngrok_api.sh
│   ├── pastebin.sh
│   ├── shields_embed_logo.sh
│   ├── termbin.sh
│   ├── traefik_api.sh
│   ├── wordpress.htaccess
│   ├── wordpress.sh
│   ├── wordpress_api.sh
│   ├── wordpress_plugins_markdown.sh
│   └── wordpress_posts_without_category_tags.sh
├── ipaas/
│   └── make_api.sh
├── java/
│   ├── bytecode_viewer.sh
│   ├── cfr.sh
│   ├── java_decompile_jar.sh
│   ├── java_show_classpath.sh
│   ├── jd_gui.sh
│   ├── jvm_heaps.sh
│   ├── jvm_heaps_total_mb.sh
│   └── procyon.sh
├── jenkins/
│   ├── README.md
│   ├── jenkins.sh
│   ├── jenkins_api.sh
│   ├── jenkins_builds.sh
│   ├── jenkins_clear_build_history.groovy
│   ├── jenkins_clear_build_history_all_jobs.groovy
│   ├── jenkins_cli.sh
│   ├── jenkins_count_jobs.groovy
│   ├── jenkins_create_job_check_gcp_serviceaccount.sh
│   ├── jenkins_create_job_parallel_test_runs.sh
│   ├── jenkins_create_run_job.sh
│   ├── jenkins_cred_add_cert.sh
│   ├── jenkins_cred_add_kubernetes_sa.sh
│   ├── jenkins_cred_add_secret_file.sh
│   ├── jenkins_cred_add_secret_text.sh
│   ├── jenkins_cred_add_ssh_key.sh
│   ├── jenkins_cred_add_user_pass.sh
│   ├── jenkins_cred_cli_add_cert.sh
│   ├── jenkins_cred_cli_add_kubernetes_sa.sh
│   ├── jenkins_cred_cli_add_secret_file.sh
│   ├── jenkins_cred_cli_add_secret_text.sh
│   ├── jenkins_cred_cli_add_ssh_key.sh
│   ├── jenkins_cred_cli_add_user_pass.sh
│   ├── jenkins_cred_cli_delete.sh
│   ├── jenkins_cred_cli_list.sh
│   ├── jenkins_cred_cli_set_cert.sh
│   ├── jenkins_cred_cli_set_kubernetes_sa.sh
│   ├── jenkins_cred_cli_set_secret_file.sh
│   ├── jenkins_cred_cli_set_secret_text.sh
│   ├── jenkins_cred_cli_set_ssh_key.sh
│   ├── jenkins_cred_cli_set_user_pass.sh
│   ├── jenkins_cred_cli_update_cert.sh
│   ├── jenkins_cred_cli_update_kubernetes_sa.sh
│   ├── jenkins_cred_cli_update_secret_file.sh
│   ├── jenkins_cred_cli_update_secret_text.sh
│   ├── jenkins_cred_cli_update_ssh_key.sh
│   ├── jenkins_cred_cli_update_user_pass.sh
│   ├── jenkins_cred_delete.sh
│   ├── jenkins_cred_get.sh
│   ├── jenkins_cred_list.sh
│   ├── jenkins_cred_set_cert.sh
│   ├── jenkins_cred_set_kubernetes_sa.sh
│   ├── jenkins_cred_set_secret_file.sh
│   ├── jenkins_cred_set_secret_text.sh
│   ├── jenkins_cred_set_ssh_key.sh
│   ├── jenkins_cred_set_user_pass.sh
│   ├── jenkins_cred_update_cert.sh
│   ├── jenkins_cred_update_kubernetes_sa.sh
│   ├── jenkins_cred_update_secret_file.sh
│   ├── jenkins_cred_update_secret_text.sh
│   ├── jenkins_cred_update_ssh_key.sh
│   ├── jenkins_cred_update_user_pass.sh
│   ├── jenkins_creds_cli_xml_dump.sh
│   ├── jenkins_foreach_job.sh
│   ├── jenkins_foreach_job_cli.sh
│   ├── jenkins_job_config.sh
│   ├── jenkins_job_description.sh
│   ├── jenkins_job_disable.groovy
│   ├── jenkins_job_disable.sh
│   ├── jenkins_job_enable.sh
│   ├── jenkins_job_trigger.sh
│   ├── jenkins_job_trigger_with_params.sh
│   ├── jenkins_jobs.groovy
│   ├── jenkins_jobs.sh
│   ├── jenkins_jobs_disable.sh
│   ├── jenkins_jobs_disabled.groovy
│   ├── jenkins_jobs_download_configs.sh
│   ├── jenkins_jobs_download_configs_cli.sh
│   ├── jenkins_jobs_enable.sh
│   ├── jenkins_jobs_status.groovy
│   ├── jenkins_password.sh
│   └── jenkins_plugins_latest_versions.sh
├── kafka/
│   ├── kafka_acls.sh
│   ├── kafka_cli_jaas.conf
│   ├── kafka_configs.sh
│   ├── kafka_console_consumer.sh
│   ├── kafka_console_producer.sh
│   ├── kafka_consumer_groups.sh
│   ├── kafka_consumer_perf_test.sh
│   ├── kafka_producer_perf_test.sh
│   └── kafka_topics.sh
├── kics.config
├── kubernetes/
│   ├── argocd_apps_sync.sh
│   ├── argocd_apps_wait_sync.sh
│   ├── argocd_auto_sync.sh
│   ├── argocd_generate_resource_whitelist.sh
│   ├── argocd_namespace_resource_whitelist.sh
│   ├── argocd_password.sh
│   ├── curl_k8s_ingress.sh
│   ├── datree_kustomize_all.sh
│   ├── helm_template.sh
│   ├── kubeadm_join_cmd.sh
│   ├── kubeadm_join_cmd2.sh
│   ├── kubectl.sh
│   ├── kubectl_alpine.sh
│   ├── kubectl_busybox.sh
│   ├── kubectl_container_count.sh
│   ├── kubectl_container_counts.sh
│   ├── kubectl_create_namespaces.sh
│   ├── kubectl_curl.sh
│   ├── kubectl_delete_empty_namespaces.sh
│   ├── kubectl_deployment_pods.sh
│   ├── kubectl_diff_apply.sh
│   ├── kubectl_dnsutils.sh
│   ├── kubectl_empty_namespaces.sh
│   ├── kubectl_exec.sh
│   ├── kubectl_exec2.sh
│   ├── kubectl_gcloud_sdk.sh
│   ├── kubectl_get_all.sh
│   ├── kubectl_get_annotation.sh
│   ├── kubectl_image_counts.sh
│   ├── kubectl_image_deployments.sh
│   ├── kubectl_images.sh
│   ├── kubectl_jobs_delete_stuck.sh
│   ├── kubectl_jobs_stuck.sh
│   ├── kubectl_kv_to_secret.sh
│   ├── kubectl_logs.sh
│   ├── kubectl_node_labels.sh
│   ├── kubectl_node_taints.sh
│   ├── kubectl_pod_count.sh
│   ├── kubectl_pod_ips.sh
│   ├── kubectl_pod_labels.sh
│   ├── kubectl_pods_colocated.sh
│   ├── kubectl_pods_dump_all.sh
│   ├── kubectl_pods_dump_jstacks.sh
│   ├── kubectl_pods_dump_logs.sh
│   ├── kubectl_pods_dump_stats.sh
│   ├── kubectl_pods_important.sh
│   ├── kubectl_pods_per_node.sh
│   ├── kubectl_pods_running_with_labels.sh
│   ├── kubectl_port_forward.sh
│   ├── kubectl_port_forward_spark.sh
│   ├── kubectl_rerun_job.sh
│   ├── kubectl_restart.sh
│   ├── kubectl_rollout_history_all_deployments.sh
│   ├── kubectl_run_sa.sh
│   ├── kubectl_secret_values.sh
│   ├── kubectl_secrets_annotate_to_be_sealed.sh
│   ├── kubectl_secrets_download.sh
│   ├── kubectl_secrets_not_sealed.sh
│   ├── kubectl_secrets_to_be_sealed.sh
│   ├── kubernetes_api.sh
│   ├── kubernetes_autoscaler_release.sh
│   ├── kubernetes_check_objects_namespaced.sh
│   ├── kubernetes_delete_stuck_namespace.sh
│   ├── kubernetes_etcd_backup.sh
│   ├── kubernetes_foreach_context.sh
│   ├── kubernetes_foreach_namespace.sh
│   ├── kubernetes_info.sh
│   ├── kubernetes_nodes_ssh_dump_logs.sh
│   ├── kubernetes_resource_types.sh
│   ├── kubernetes_secret_to_external_secret_gcp.sh
│   ├── kubernetes_secret_to_sealed_secret.sh
│   ├── kubernetes_secrets_compare_gcp_secret_manager.sh
│   ├── kubernetes_secrets_to_external_secrets_gcp.sh
│   ├── kubernetes_secrets_to_sealed_secrets.sh
│   ├── kubernetes_yaml_strip_live_fields.sh
│   ├── kustomize_check_objects_namespaced.sh
│   ├── kustomize_diff_apply.sh
│   ├── kustomize_diff_branch.sh
│   ├── kustomize_install_helm_charts.sh
│   ├── kustomize_materialize.sh
│   ├── kustomize_parse_helm_charts.sh
│   ├── kustomize_update_helm_chart_versions.sh
│   ├── pluto_detect_helm_materialize.sh
│   ├── pluto_detect_kubectl_dump_objects.sh
│   ├── pluto_detect_kustomize_materialize.sh
│   ├── rancher_api.sh
│   └── rancher_kube_creds.sh
├── lib/
│   ├── README.md
│   ├── args_extract.sh
│   ├── aws.sh
│   ├── bitbucket.sh
│   ├── ci.sh
│   ├── cloudera_manager.sh
│   ├── cloudera_navigator.sh
│   ├── dbshell.sh
│   ├── docker.sh
│   ├── dockerfile_keywords.txt
│   ├── excluded.sh
│   ├── gcp.sh
│   ├── gcp_ci.sh
│   ├── git.sh
│   ├── github.sh
│   ├── gitlab.sh
│   ├── kubernetes.sh
│   ├── mac.sh
│   ├── mp3.sh
│   ├── os.sh
│   ├── packages.sh
│   ├── perl.sh
│   ├── python.sh
│   ├── ruby.sh
│   ├── spotify.sh
│   ├── sql.sh
│   ├── travis.sh
│   ├── utils-bourne.sh
│   └── utils.sh
├── markdown/
│   ├── markdown_columns_to_table.sh
│   ├── markdown_generate_index.sh
│   ├── markdown_list_indentations.sh
│   ├── markdown_octocat_github_links.sh
│   ├── markdown_replace_index.sh
│   ├── markdown_replace_links_with_jsdelivr.sh
│   ├── markdown_replace_repos.sh
│   └── mdl_list_indentations.sh
├── media/
│   ├── asciinema.sh
│   ├── avi_to_mp4.sh
│   ├── avif_to_png.sh
│   ├── image_join_vertical.sh
│   ├── image_reduce_quality.sh
│   ├── image_shrink.sh
│   ├── image_to_png.sh
│   ├── image_trim_pixels.sh
│   ├── imageopen.sh
│   ├── mkv_to_mp4.sh
│   ├── mp3_set_album.sh
│   ├── mp3_set_artist.sh
│   ├── mp3_set_track_name.sh
│   ├── mp3_set_track_order.sh
│   ├── svg_to_png.sh
│   ├── terminalizer.sh
│   ├── ttygif.sh
│   ├── video_to_720p_mp4.sh
│   ├── vidopen.sh
│   ├── webp_to_png.sh
│   ├── youtube_download_channel.sh
│   └── youtube_download_video.sh
├── monitoring/
│   ├── dump_stats.sh
│   ├── log_timestamp_large_intervals.sh
│   ├── prometheus.sh
│   ├── prometheus_docker.sh
│   ├── prometheus_node_exporter.sh
│   ├── ssh_dump_logs.sh
│   └── ssh_dump_stats.sh
├── mysql/
│   ├── mariadb.sh
│   ├── mariadb_test_scripts.sh
│   ├── mysql.sh
│   ├── mysql_foreach_table.sh
│   ├── mysql_list_databases.sh
│   ├── mysql_list_tables.sh
│   ├── mysql_tables_row_counts.sh
│   ├── mysql_test_scripts.sh
│   └── mysqld.sh
├── packages/
│   ├── apk_filter_installed.sh
│   ├── apk_filter_not_installed.sh
│   ├── apk_install_packages.sh
│   ├── apk_install_packages_if_absent.sh
│   ├── apk_remove_packages.sh
│   ├── apk_upgrade_packages_if_outdated.sh
│   ├── apt_install_packages.sh
│   ├── apt_install_packages_if_absent.sh
│   ├── apt_remove_packages.sh
│   ├── apt_set_lock_timeout.sh
│   ├── apt_upgrade_packages_if_outdated.sh
│   ├── apt_wait.sh
│   ├── brew_filter_in_setup.sh
│   ├── brew_filter_installed.sh
│   ├── brew_filter_not_in_setup.sh
│   ├── brew_filter_not_installed.sh
│   ├── brew_install_packages.sh
│   ├── brew_install_packages_if_absent.sh
│   ├── brew_package_owns.sh
│   ├── brew_upgrade_packages.sh
│   ├── brew_upgrade_packages_if_outdated.sh
│   ├── debs_filter_installed.sh
│   ├── debs_filter_not_installed.sh
│   ├── golang_install.sh
│   ├── golang_install_if_absent.sh
│   ├── golang_rm_binaries.sh
│   ├── install_binary.sh
│   ├── install_packages.sh
│   ├── install_packages_if_absent.sh
│   ├── nodejs_npm_install.sh
│   ├── nodejs_npm_install_if_absent.sh
│   ├── rpms_filter_installed.sh
│   ├── rpms_filter_not_installed.sh
│   ├── ruby_gem_install.sh
│   ├── ruby_gem_install_if_absent.sh
│   ├── upgrade_packages_if_outdated.sh
│   ├── yum_install_packages.sh
│   ├── yum_install_packages_if_absent.sh
│   ├── yum_remove_packages.sh
│   └── yum_upgrade_packages_if_outdated.sh
├── perl/
│   ├── perl_cpanm_install.sh
│   ├── perl_cpanm_install_if_absent.sh
│   ├── perl_cpanm_reinstall_all.sh
│   ├── perl_find_duplicate_cpan_requirements.sh
│   ├── perl_find_library_executable.sh
│   ├── perl_find_library_path.sh
│   ├── perl_find_unused_cpan_modules.sh
│   ├── perl_generate_fatpacks.sh
│   ├── perl_generate_par_binaries.sh
│   └── perlpath.sh
├── pingdom/
│   ├── pingdom_api.sh
│   ├── pingdom_check_latency_by_hour.sh
│   ├── pingdom_check_outages.sh
│   ├── pingdom_checks.sh
│   ├── pingdom_checks_average_response_times.sh
│   ├── pingdom_checks_latency_by_hour.sh
│   ├── pingdom_checks_outages.sh
│   ├── pingdom_foreach_check.sh
│   └── pingdom_sms_credits.sh
├── postgres/
│   ├── postgres.sh
│   ├── postgres_foreach_table.sh
│   ├── postgres_foreach_table_timeout.sh
│   ├── postgres_list_databases.sh
│   ├── postgres_list_schemas.sh
│   ├── postgres_list_tables.sh
│   ├── postgres_tables_row_counts.sh
│   ├── postgres_test_scripts.sh
│   ├── psql.sh
│   └── psql_colorized.sh
├── python/
│   ├── pygmentize.sh
│   ├── python_compile.sh
│   ├── python_find_duplicate_pip_requirements.sh
│   ├── python_find_library_executable.sh
│   ├── python_find_library_path.sh
│   ├── python_find_unused_pip_modules.sh
│   ├── python_indices.sh
│   ├── python_pip_install.sh
│   ├── python_pip_install_for_script.sh
│   ├── python_pip_install_if_absent.sh
│   ├── python_pip_reinstall_all_modules.sh
│   ├── python_pyinstaller.sh
│   ├── python_pypi_versions.sh
│   ├── python_translate_import_to_module.sh
│   ├── python_translate_module_to_import.sh
│   └── pythonpath.sh
├── requirements.txt
├── resources/
│   ├── oreilly-animals.json
│   ├── pipreqs_mapping.txt
│   ├── tabs_ignore.txt
│   └── whitespace_ignore.txt
├── scalastyle_config.xml
├── scripts/
│   ├── README.md
│   ├── git_capitalize_urls.sh
│   ├── spotify_commit_playlists.sh
│   ├── spotify_commit_rename_playlist.sh
│   ├── spotify_rename_playlist_files.sh
│   └── update_bash_tools_references.sh
├── search/
│   ├── solr_api.sh
│   ├── solr_collection_check_exists.sh
│   └── solr_collection_create_if_not_exists.sh
├── setup/
│   ├── Hari.terminal
│   ├── R-packages.txt
│   ├── README.md
│   ├── alternatives_set_python.sh
│   ├── apk-packages-desktop.txt
│   ├── apk-packages-optional.txt
│   ├── apk-packages.txt
│   ├── atom-packages.txt
│   ├── bootstrap.sh
│   ├── brew-packages-desktop-casks.txt
│   ├── brew-packages-desktop-taps.txt
│   ├── brew-packages-desktop.txt
│   ├── brew-packages-ignore.txt
│   ├── brew-packages.txt
│   ├── brew_fix_openssl_dependencies.sh
│   ├── brew_packages_not_saved.sh
│   ├── ccmenu_cp_plist.sh
│   ├── ccmenu_setup.sh
│   ├── ci.txt
│   ├── ci_bootstrap.sh
│   ├── ci_git_set_dir_safe.sh
│   ├── cpan-packages-desktop.txt
│   ├── cpan-requirements-optional.txt
│   ├── cpan-requirements.txt
│   ├── deb-packages-desktop.txt
│   ├── deb-packages-optional.txt
│   ├── deb-packages.txt
│   ├── debian.experimental.pref
│   ├── debian.stable.pref
│   ├── debian.testing.pref
│   ├── debian.unstable.pref
│   ├── docker-images.txt
│   ├── docker_bootstrap.sh
│   ├── download_cassandra.sh
│   ├── download_openjdk11.sh
│   ├── files.txt
│   ├── gem-packages-desktop.txt
│   ├── gem-packages.txt
│   ├── go-packages-desktop.txt
│   ├── gocd_config_repo.json
│   ├── intellij-plugins.txt
│   ├── jenkins-job-check-gcp-serviceaccount.xml
│   ├── jenkins-job-sleep-parallel-parameterized.xml
│   ├── jenkins-job.xml
│   ├── jenkins-plugins.txt
│   ├── linux_desktop.sh
│   ├── mac_delete_routes_on_interface.sh
│   ├── mac_desktop.sh
│   ├── mac_diff_settings.sh
│   ├── mac_settings.sh
│   ├── mac_spotlight_config_optimize.sh
│   ├── mas-packages.txt
│   ├── npm-packages-desktop.txt
│   ├── npm-packages.txt
│   ├── pip-packages-desktop.txt
│   ├── pip-packages-mac.txt
│   ├── pip_fix_version.sh
│   ├── portage-packages-desktop.txt
│   ├── portage-packages-dockapps.txt
│   ├── portage-packages-extras.txt
│   ├── portage-packages-server.txt
│   ├── postgresql.conf
│   ├── prometheus.yml
│   ├── python_install_snakebite.sh
│   ├── python_mac_upgrade_ssl_fix.sh
│   ├── repos.txt
│   ├── rpm-packages-desktop.txt
│   ├── rpm-packages-optional.txt
│   ├── rpm-packages.txt
│   ├── setup_codefresh.sh
│   ├── shell_link.sh
│   ├── shell_unlink.sh
│   ├── squirrelsql-install-options.xml
│   ├── teamcity/
│   │   └── teamcity-database.properties
│   ├── teamcity-mysql-setup.sql
│   ├── upgrade_gradle_wrapper.sh
│   └── which_python_installed.sh
├── shippable/
│   ├── shippable.yml
│   ├── shippable_account_id.sh
│   ├── shippable_api.sh
│   ├── shippable_builds.sh
│   ├── shippable_project_builds.sh
│   └── shippable_projects.sh
├── sonar-project.properties
├── spotify/
│   ├── spotify_add_artist_to_backlog_playlist.sh
│   ├── spotify_add_to_playlist.sh
│   ├── spotify_api.sh
│   ├── spotify_api_token.sh
│   ├── spotify_artist_tracks.sh
│   ├── spotify_artists_followed.sh
│   ├── spotify_artists_followed_uri.sh
│   ├── spotify_artists_followed_uri_name.sh
│   ├── spotify_backup.sh
│   ├── spotify_backup_artists_followed.sh
│   ├── spotify_backup_playlist.sh
│   ├── spotify_backup_playlists.sh
│   ├── spotify_backup_playlists_list.sh
│   ├── spotify_callback_openssl.cnf
│   ├── spotify_create_playlist.sh
│   ├── spotify_delete_any_duplicates_in_playlist.sh
│   ├── spotify_delete_duplicate_track_uris_in_playlist.sh
│   ├── spotify_delete_duplicate_tracks_in_playlists.sh
│   ├── spotify_delete_from_playlist.sh
│   ├── spotify_delete_from_playlist_if_in_other_playlists.sh
│   ├── spotify_delete_from_playlist_if_track_in_other_playlists.sh
│   ├── spotify_duplicate_tracks_in_playlist.sh
│   ├── spotify_duplicate_uri_in_playlist.sh
│   ├── spotify_filename_to_playlist.sh
│   ├── spotify_follow_artists.sh
│   ├── spotify_follow_liked_artists.sh
│   ├── spotify_follow_top_artists.sh
│   ├── spotify_foreach_playlist.sh
│   ├── spotify_liked_artists.sh
│   ├── spotify_liked_artists_uri.sh
│   ├── spotify_liked_tracks.sh
│   ├── spotify_liked_tracks_uri.sh
│   ├── spotify_liked_uri_artist_track.sh
│   ├── spotify_playlist_artists.sh
│   ├── spotify_playlist_id_to_name.sh
│   ├── spotify_playlist_json.sh
│   ├── spotify_playlist_name_to_id.sh
│   ├── spotify_playlist_snapshot_id.sh
│   ├── spotify_playlist_to_filename.sh
│   ├── spotify_playlist_top_artists.sh
│   ├── spotify_playlist_tracks.sh
│   ├── spotify_playlist_tracks_uri.sh
│   ├── spotify_playlist_tracks_uri_artist_track.sh
│   ├── spotify_playlist_tracks_uri_batch_by_year.sh
│   ├── spotify_playlist_tracks_uri_by_year.sh
│   ├── spotify_playlist_tracks_uri_in_year.sh
│   ├── spotify_playlist_uri_offset.sh
│   ├── spotify_playlists.sh
│   ├── spotify_playlists_json.sh
│   ├── spotify_release_year.sh
│   ├── spotify_rename_playlist.sh
│   ├── spotify_search.sh
│   ├── spotify_search_alternate_track_uris.sh
│   ├── spotify_search_json.sh
│   ├── spotify_search_uri.sh
│   ├── spotify_set_playlists_private.sh
│   ├── spotify_set_playlists_public.sh
│   ├── spotify_set_tracks_uri_to_liked.sh
│   ├── spotify_top_artists.sh
│   ├── spotify_top_artists_uri.sh
│   ├── spotify_top_tracks.sh
│   ├── spotify_top_tracks_uri.sh
│   ├── spotify_uri_json.sh
│   └── spotify_uri_to_name.sh
├── teamcity/
│   ├── .teamcity.vcs.json
│   ├── .teamcity.vcs.oauth.json
│   ├── .teamcity.vcs.ssh.json
│   ├── teamcity.sh
│   ├── teamcity_agents.sh
│   ├── teamcity_api.sh
│   ├── teamcity_builds.sh
│   ├── teamcity_buildtype_create.sh
│   ├── teamcity_buildtype_set_description_from_github.sh
│   ├── teamcity_buildtypes.sh
│   ├── teamcity_buildtypes_set_description_from_github.sh
│   ├── teamcity_create_github_oauth_connection.sh
│   ├── teamcity_create_project.sh
│   ├── teamcity_create_vcs_root.sh
│   ├── teamcity_export.sh
│   ├── teamcity_export_buildtypes.sh
│   ├── teamcity_export_project_config.sh
│   ├── teamcity_export_vcs_roots.sh
│   ├── teamcity_project_set_versioned_settings.sh
│   ├── teamcity_project_vcs_versioning.sh
│   ├── teamcity_projects.sh
│   ├── teamcity_upload_ssh_key.sh
│   └── teamcity_vcs_roots.sh
├── terraform/
│   ├── terraform_cloud_api.sh
│   ├── terraform_cloud_ip_ranges.sh
│   ├── terraform_cloud_organizations.sh
│   ├── terraform_cloud_varset_delete_vars.sh
│   ├── terraform_cloud_varset_set_vars.sh
│   ├── terraform_cloud_varset_vars.sh
│   ├── terraform_cloud_varsets.sh
│   ├── terraform_cloud_workspace_delete_vars.sh
│   ├── terraform_cloud_workspace_set_vars.sh
│   ├── terraform_cloud_workspace_vars.sh
│   ├── terraform_cloud_workspaces.sh
│   ├── terraform_gcs_backend_version.sh
│   ├── terraform_gitlab_download_backend_variable.sh
│   ├── terraform_import.sh
│   ├── terraform_import_aws_iam_groups.sh
│   ├── terraform_import_aws_iam_policies.sh
│   ├── terraform_import_aws_iam_users.sh
│   ├── terraform_import_aws_sso_account_assignments.sh
│   ├── terraform_import_aws_sso_managed_policy_attachments.sh
│   ├── terraform_import_aws_sso_permission_set_inline_policies.sh
│   ├── terraform_import_aws_sso_permission_sets.sh
│   ├── terraform_import_foreach.sh
│   ├── terraform_import_github_repos.sh
│   ├── terraform_import_github_team.sh
│   ├── terraform_import_github_team_repos.sh
│   ├── terraform_import_github_teams.sh
│   ├── terraform_managed_resource_types.sh
│   ├── terraform_provider_count_sizes.sh
│   ├── terraform_registry_url_extract.sh
│   ├── terraform_registry_url_open.sh
│   ├── terraform_registry_url_to_https.sh
│   └── terraform_resources.sh
├── tests/
│   ├── README.md
│   ├── azure_devops_url_conversion.sh
│   └── test_spotify_uri_to_name.sh
├── travis/
│   ├── .travis.yml
│   ├── travis_api.sh
│   ├── travis_delete_cron.sh
│   ├── travis_foreach_repo.sh
│   ├── travis_lint.sh
│   ├── travis_repo_build.sh
│   ├── travis_repo_caches.sh
│   ├── travis_repo_create_cron.sh
│   ├── travis_repo_crons.sh
│   ├── travis_repo_delete_caches.sh
│   ├── travis_repo_delete_crons.sh
│   ├── travis_repo_env_vars.sh
│   ├── travis_repo_settings.sh
│   ├── travis_repos.sh
│   ├── travis_repos_caches.sh
│   ├── travis_repos_create_cron.sh
│   ├── travis_repos_crons.sh
│   ├── travis_repos_delete_caches.sh
│   ├── travis_repos_delete_crons.sh
│   └── travis_repos_settings.sh
├── vagrant/
│   ├── vagrant_hosts.sh
│   └── vagrant_total_mb.sh
├── wercker/
│   ├── .werckerignore
│   ├── wercker.yml
│   ├── wercker_api_app.sh
│   ├── wercker_api_runs.sh
│   ├── wercker_api_workflows.sh
│   └── wercker_app_id.sh
└── yamllint/
    └── config
Condensed preview — 1804 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (5,428K chars).
[
  {
    "path": ".appveyor.yml",
    "chars": 3963,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2020-02-24 16:19:35 +0000 (Mon, 24 Feb 2020)\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://"
  },
  {
    "path": ".bash.d/Makefile",
    "chars": 529,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2016-01-17 12:56:53 +0000 (Sun, 17 Jan 2016)\n#\n#  vim:ts=4:sts=4:sw=4:noet\n#\n#  https:"
  },
  {
    "path": ".bash.d/README.md",
    "chars": 4410,
    "preview": "Advanced Bashrc Code - Interactive Functions, Aliases and Shell Customizations\n========================================="
  },
  {
    "path": ".bash.d/aliases.sh",
    "chars": 11698,
    "preview": "#!/usr/bin/env bash\n# shellcheck disable=SC2230,SC2139\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: circa"
  },
  {
    "path": ".bash.d/android.sh",
    "chars": 766,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2025-02-27 02:08:34 +0700 (Thu, 27 Feb 2"
  },
  {
    "path": ".bash.d/ansible.sh",
    "chars": 2177,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#  shellcheck disable=SC2139\n#\n#  Author: Hari Sekhon\n#  Date: 2014-07-13 "
  },
  {
    "path": ".bash.d/argocd.sh",
    "chars": 1942,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2022-01-07 16:03:39 +0000 (Fri, 07 Jan 2"
  },
  {
    "path": ".bash.d/aws-cloudshell.sh",
    "chars": 1511,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2020-12-17 18:54:23 +0000 (Thu, 17 Dec 2"
  },
  {
    "path": ".bash.d/aws.sh",
    "chars": 8809,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2012-09-01 13:01:11 +0100\n#\n#  https://g"
  },
  {
    "path": ".bash.d/azure.sh",
    "chars": 1134,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#  shellcheck disable=SC1090,SC1091\n#\n#  Author: Hari Sekhon\n#  Date: 2020"
  },
  {
    "path": ".bash.d/bash_it.sh",
    "chars": 813,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2020-02-26 15:21:46 +0000 (Wed, 26 Feb 2"
  },
  {
    "path": ".bash.d/circleci.sh",
    "chars": 1020,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2022-08-02 12:21:34 +0100 (Tue, 02 Aug 2"
  },
  {
    "path": ".bash.d/colors.sh",
    "chars": 2931,
    "preview": "#!/usr/bin/env bash\n#  shellcheck disable=SC2034\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2012-06-25 "
  },
  {
    "path": ".bash.d/custom.sh",
    "chars": 1779,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2006-06-28 23:25:09 +0100 (Wed, 28 Jun 2"
  },
  {
    "path": ".bash.d/direnv.sh",
    "chars": 1077,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2020-04-10 13:02:46 +0100 (Fri, 10 Apr 2"
  },
  {
    "path": ".bash.d/docker.sh",
    "chars": 9611,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2015-11-05 20:53:32 +0000\n#\n#  https://g"
  },
  {
    "path": ".bash.d/env.sh",
    "chars": 5530,
    "preview": "#!/usr/bin/env bash\n# shellcheck disable=SC2230\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: circa 2006 ("
  },
  {
    "path": ".bash.d/functions.sh",
    "chars": 19202,
    "preview": "#!/usr/bin/env bash\n# shellcheck disable=SC2230\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: circa 2006 ("
  },
  {
    "path": ".bash.d/gcp.sh",
    "chars": 2917,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#  shellcheck disable=SC1090,SC1091\n#\n#  Author: Hari Sekhon\n#  Date: 2019"
  },
  {
    "path": ".bash.d/git.sh",
    "chars": 32308,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: circa 2006 (forked from .bashrc)\n#\n#  ht"
  },
  {
    "path": ".bash.d/golang.sh",
    "chars": 2425,
    "preview": "#!/usr/bin/env bash\n# shellcheck disable=SC2230\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: circa 2015 ("
  },
  {
    "path": ".bash.d/gpg-agent.sh",
    "chars": 2212,
    "preview": "#!/usr/bin/env bash\n# shellcheck disable=SC2230\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: circa 2006 ("
  },
  {
    "path": ".bash.d/grype.sh",
    "chars": 852,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2022-01-10 17:58:03 +0000 (Mon, 10 Jan 2"
  },
  {
    "path": ".bash.d/hadoop.sh",
    "chars": 2771,
    "preview": "#!/usr/bin/env bash\n# shellcheck disable=SC2230\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: circa 2009+ "
  },
  {
    "path": ".bash.d/intellij.sh",
    "chars": 4098,
    "preview": "#!/usr/bin/env bash\n# shellcheck disable=SC2230\n#\n#  Author: Hari Sekhon\n#  Date: 2023-07-26 00:10:06 +0100\n#\n#  vim:ts="
  },
  {
    "path": ".bash.d/java.sh",
    "chars": 5295,
    "preview": "#!/usr/bin/env bash\n# shellcheck disable=SC2230\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: Sun Sep 9 21"
  },
  {
    "path": ".bash.d/jenkins.sh",
    "chars": 1687,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2021-02-22 17:18:09 +0000 (Mon, 22 Feb 2"
  },
  {
    "path": ".bash.d/k3d.sh",
    "chars": 818,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2023-04-03 20:30:17 +0100 (Mon, 03 Apr 2"
  },
  {
    "path": ".bash.d/kafka.sh",
    "chars": 3015,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2019-07-28 14:46:37 +0100 (Sun, 28 Jul 2"
  },
  {
    "path": ".bash.d/kubernetes.sh",
    "chars": 19743,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2019-07-28 14:56:41 +0100 (Sun, 28 Jul 2"
  },
  {
    "path": ".bash.d/linux.sh",
    "chars": 3650,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2006 (forked from .bashrc)\n#\n#  https://"
  },
  {
    "path": ".bash.d/lolcat.sh",
    "chars": 467,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2019-11-03 11:31:02 +0000 (Sun, 03 Nov 2"
  },
  {
    "path": ".bash.d/mac.sh",
    "chars": 7299,
    "preview": "#!/usr/bin/env bash\n# shellcheck disable=SC2230\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: circa 2011 ("
  },
  {
    "path": ".bash.d/mercurial.sh",
    "chars": 6608,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: circa 2012 (forked from .bashrc)\n#\n#  ht"
  },
  {
    "path": ".bash.d/mp3.sh",
    "chars": 1415,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2020-07-21 11:36:49 +0100 (Tue, 21 Jul 2"
  },
  {
    "path": ".bash.d/mysql.sh",
    "chars": 994,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2020-03-16 13:26:50 +0000 (Mon, 16 Mar 2"
  },
  {
    "path": ".bash.d/network.sh",
    "chars": 13371,
    "preview": "#!/usr/bin/env bash\n# shellcheck disable=SC2230\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: circa 2006 -"
  },
  {
    "path": ".bash.d/nodejs.sh",
    "chars": 1170,
    "preview": "#!/usr/bin/env bash\n# shellcheck disable=SC2230\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: circa 2019 ("
  },
  {
    "path": ".bash.d/os_detection.sh",
    "chars": 2082,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: circa 2010 - 2012 (forked from .bashrc)\n"
  },
  {
    "path": ".bash.d/paths.sh",
    "chars": 16885,
    "preview": "#!/usr/bin/env bash\n# shellcheck disable=SC2230\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: circa 2006 ("
  },
  {
    "path": ".bash.d/perl.sh",
    "chars": 2226,
    "preview": "#!/usr/bin/env bash\n# shellcheck disable=SC2230\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: circa 2006 ("
  },
  {
    "path": ".bash.d/postgres.sh",
    "chars": 975,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2020-03-16 13:20:17 +0000 (Mon, 16 Mar 2"
  },
  {
    "path": ".bash.d/prompt.sh",
    "chars": 3708,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: circa 2006 - 2012 (forked from .bashrc)\n"
  },
  {
    "path": ".bash.d/python.sh",
    "chars": 2245,
    "preview": "#!/usr/bin/env bash\n# shellcheck disable=SC2230\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: circa 2006 ("
  },
  {
    "path": ".bash.d/rancid.sh",
    "chars": 2095,
    "preview": "#!/usr/bin/env bash\n# shellcheck disable=SC2230\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: circa 2010 -"
  },
  {
    "path": ".bash.d/ruby.sh",
    "chars": 2793,
    "preview": "#!/usr/bin/env bash\n# shellcheck disable=SC2230\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: circa 2012 ("
  },
  {
    "path": ".bash.d/screen.sh",
    "chars": 2601,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: circa 2006 - 2012 (forked from .bashrc)\n"
  },
  {
    "path": ".bash.d/skaffold.sh",
    "chars": 829,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2021-07-05 16:31:14 +0100 (Mon, 05 Jul 2"
  },
  {
    "path": ".bash.d/spinner.sh",
    "chars": 1262,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2012-06-25 15:20:39\n#\n#  https://github."
  },
  {
    "path": ".bash.d/spotify.sh",
    "chars": 1938,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2020-07-18 19:43:00 +0100 (Sat, 18 Jul 2"
  },
  {
    "path": ".bash.d/ssh-agent.sh",
    "chars": 2169,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: circa 2006 (forked from .bashrc)\n#\n#  ht"
  },
  {
    "path": ".bash.d/ssh.sh",
    "chars": 7074,
    "preview": "#!/usr/bin/env bash\n# shellcheck disable=SC2230\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: circa 2006 -"
  },
  {
    "path": ".bash.d/svn.sh",
    "chars": 5332,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: circa 2006 (forked from .bashrc)\n#\n#  ht"
  },
  {
    "path": ".bash.d/teamcity.sh",
    "chars": 1327,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2020-11-24 17:09:11 +0000 (Tue, 24 Nov 2"
  },
  {
    "path": ".bash.d/terraform.sh",
    "chars": 4172,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2020-09-24 18:02:04 +0100 (Thu, 24 Sep 2"
  },
  {
    "path": ".bash.d/title.sh",
    "chars": 4060,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: circa 2006 - 2012 (forked from .bashrc)\n"
  },
  {
    "path": ".bash.d/travis_ci.sh",
    "chars": 1873,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: Wed Jan 20 15:28:12 2016 +0000\n#\n#  http"
  },
  {
    "path": ".bash.d/trivy.sh",
    "chars": 823,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2023-05-12 06:50:49 +0100 (Fri, 12 May 2"
  },
  {
    "path": ".bash.d/vagrant.sh",
    "chars": 5078,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: Thu Mar 14 12:42:17 2013 +0000\n#\n#  http"
  },
  {
    "path": ".bash.d/vim.sh",
    "chars": 2800,
    "preview": "#!/usr/bin/env bash\n# shellcheck disable=SC2230\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: circa 2006 ("
  },
  {
    "path": ".bash.d/virtualbox.sh",
    "chars": 1359,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2015-01-14 22:13:51 +0000\n#  Original: c"
  },
  {
    "path": ".bash.d/vnc.sh",
    "chars": 2241,
    "preview": "#!/usr/bin/env bash\n# shellcheck disable=SC2230\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: circa 2006 -"
  },
  {
    "path": ".bash.d/welcome.sh",
    "chars": 2625,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2012-06-25 15:20:39 +0100\n#\n#  https://g"
  },
  {
    "path": ".bash.d/when.sh",
    "chars": 3139,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: circa 2006 - 2012 (forked from .bashrc)\n"
  },
  {
    "path": ".bash.d/z_final.sh",
    "chars": 758,
    "preview": "#!/usr/bin/env bash\n# shellcheck disable=SC2230\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: circa 2006 ("
  },
  {
    "path": ".bash_logout",
    "chars": 1028,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2006-06-28 23:25:09 +0100 (Wed, 28 Jun 2"
  },
  {
    "path": ".bash_profile",
    "chars": 1458,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2006-06-28 23:25:09 +0100 (Wed, 28 Jun 2006)\n#\n\n# ~/.bash_profile: executed by bash(1)"
  },
  {
    "path": ".bashrc",
    "chars": 5643,
    "preview": "#!/usr/bin/env bash\n#  shellcheck disable=SC1091\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2006-06-28 "
  },
  {
    "path": ".buildkite/pipeline.yml",
    "chars": 1783,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2020-03-13 21:10:39 +0000 (Fri, 13 Mar 2020)\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://"
  },
  {
    "path": ".circleci/config.yml",
    "chars": 1510,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2020-02-23 23:30:14 +0000 (Sun, 23 Feb 2020)\n#  Original: H1 2016 (Circle CI 1.x)\n#\n# "
  },
  {
    "path": ".cirrus.yml",
    "chars": 813,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2020-02-24 16:55:36 +0000 (Mon, 24 Feb 2020)\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://"
  },
  {
    "path": ".dockerignore",
    "chars": 86563,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Sep 12 13:06:25 2017 +0200\n#\n#  vim: filetype=conf\n#\n\n# =========================="
  },
  {
    "path": ".drone.yml",
    "chars": 1180,
    "preview": "---\n# XXX: putting this separator further down with code causes a parsing bug in drone lint\n#\n#  Author: Hari Sekhon\n#  "
  },
  {
    "path": ".editorconfig",
    "chars": 1953,
    "preview": "#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2015-10-31 19:04:34 +0000 (Sat, 31 Oct 2015)\n#\n#  https://gi"
  },
  {
    "path": ".envrc",
    "chars": 7549,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: Mon Feb 22 17:42:01 2021 +0000\n#\n#  http"
  },
  {
    "path": ".envrc-aws",
    "chars": 6504,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2021-07-27 12:42:32 +0100 (Tue, 27 Jul 2"
  },
  {
    "path": ".envrc-gcp",
    "chars": 5608,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: Mon Feb 22 17:42:01 2021 +0000\n#\n#  http"
  },
  {
    "path": ".envrc-java",
    "chars": 1362,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2025-03-20 01:55:20 +0800 (Thu, 20 Mar 2"
  },
  {
    "path": ".envrc-kubernetes",
    "chars": 6189,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2021-02-25 10:10:53 +0000 (Thu, 25 Feb 2"
  },
  {
    "path": ".envrc-python",
    "chars": 1337,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: Mon Feb 22 17:42:01 2021 +0000\n#\n#  http"
  },
  {
    "path": ".envrc-terraform",
    "chars": 3422,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: Mon Feb 22 17:42:01 2021 +0000\n#\n#  http"
  },
  {
    "path": ".git-templates/git-secrets/hooks/commit-msg",
    "chars": 58,
    "preview": "#!/usr/bin/env bash\ngit secrets --commit_msg_hook -- \"$@\"\n"
  },
  {
    "path": ".git-templates/git-secrets/hooks/pre-commit",
    "chars": 58,
    "preview": "#!/usr/bin/env bash\ngit secrets --pre_commit_hook -- \"$@\"\n"
  },
  {
    "path": ".git-templates/git-secrets/hooks/prepare-commit-msg",
    "chars": 66,
    "preview": "#!/usr/bin/env bash\ngit secrets --prepare_commit_msg_hook -- \"$@\"\n"
  },
  {
    "path": ".gitconfig",
    "chars": 10597,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2012-01-31 14:08:42 +0000 (Tue, 31 Jan 2012)\n#\n#  vim:ts=4:sts=4:sw=4:et\n\n# configure "
  },
  {
    "path": ".gitconfig.local",
    "chars": 145,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2012-01-31 14:08:42 +0000 (Tue, 31 Jan 2012)\n#\n\n[user]\n    name = Hari Sekhon\n    emai"
  },
  {
    "path": ".github/CODEOWNERS",
    "chars": 1524,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2021-11-09 15:14:59 +0000 (Tue, 09 Nov 2021)\n#\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  https://"
  },
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "chars": 466,
    "preview": "Please be specific about your issue and include debug output from running after setting `export DEBUG=1` in your shell.\n"
  },
  {
    "path": ".github/workflows/actions-allowed.txt",
    "chars": 862,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2022-01-26 19:04:03 +0000 (Wed, 26 Jan 2022)\n#\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  https://"
  },
  {
    "path": ".github/workflows/alpine.yaml",
    "chars": 1942,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/alpine_3.yaml",
    "chars": 1941,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/centos.yaml.disabled",
    "chars": 1905,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/centos7.yaml.disabled",
    "chars": 1903,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/centos8.yaml.disabled",
    "chars": 1903,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/checkov.yaml",
    "chars": 1454,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/codeowners.yaml",
    "chars": 1423,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/commit_adjacent_repos.sh",
    "chars": 70,
    "preview": "#!/usr/bin/env bash\n\ngit_foreach_repo.sh 'gitu .github/workflows ||:'\n"
  },
  {
    "path": ".github/workflows/debian.yaml",
    "chars": 1942,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/debian_10.yaml",
    "chars": 1944,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/debian_11.yaml",
    "chars": 1944,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/debian_12.yaml",
    "chars": 1944,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/debian_6.yaml.disabled",
    "chars": 1934,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/debian_7.yaml.disabled",
    "chars": 1934,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/debian_8.yaml.disabled",
    "chars": 1904,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/debian_9.yaml.disabled",
    "chars": 1904,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/docker_bash_alpine.yaml",
    "chars": 2480,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2022-01-27 18:55:16 +0000 (Thu, 27 Jan 2022)\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://"
  },
  {
    "path": ".github/workflows/docker_bash_centos.yaml",
    "chars": 2480,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2022-01-27 18:55:16 +0000 (Thu, 27 Jan 2022)\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://"
  },
  {
    "path": ".github/workflows/docker_bash_debian.yaml",
    "chars": 2480,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2022-01-27 18:55:16 +0000 (Thu, 27 Jan 2022)\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://"
  },
  {
    "path": ".github/workflows/docker_bash_fedora.yaml",
    "chars": 2480,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2022-01-27 18:55:16 +0000 (Thu, 27 Jan 2022)\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://"
  },
  {
    "path": ".github/workflows/docker_bash_ubuntu.yaml",
    "chars": 2562,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2022-01-27 18:55:16 +0000 (Thu, 27 Jan 2022)\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://"
  },
  {
    "path": ".github/workflows/dockerhub_status_alpine.yaml.disabled",
    "chars": 1455,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/dockerhub_status_centos.yaml.disabled",
    "chars": 1455,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/dockerhub_status_debian.yaml.disabled",
    "chars": 1455,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/dockerhub_status_fedora.yaml.disabled",
    "chars": 1455,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/dockerhub_status_ubuntu.yaml.disabled",
    "chars": 1455,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/fedora.yaml",
    "chars": 1935,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/fork-sync.yaml",
    "chars": 1306,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/fork-update-pr.yaml",
    "chars": 1439,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/ghcr_bash_ubuntu.yaml.disabled",
    "chars": 1149,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2022-02-09 18:07:10 +0000 (Wed, 09 Feb 2022)\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://"
  },
  {
    "path": ".github/workflows/grype.yaml",
    "chars": 1405,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2023-05-13 01:07:56 +0100 (Sat, 13 May 2023)\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://"
  },
  {
    "path": ".github/workflows/json.yaml",
    "chars": 1372,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/kics.yaml",
    "chars": 1400,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2022-02-01 19:36:08 +0000 (Tue, 01 Feb 2022)\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://"
  },
  {
    "path": ".github/workflows/mac.yaml",
    "chars": 1937,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/mac_11.yaml",
    "chars": 1936,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/mac_12.yaml",
    "chars": 1936,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/markdown.yaml",
    "chars": 1302,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2023-04-14 23:53:43 +0100 (Fri, 14 Apr 2023)\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://"
  },
  {
    "path": ".github/workflows/push_all_repos.sh",
    "chars": 48,
    "preview": "#!/usr/bin/env bash\n\ngit_foreach_repo.sh 'push'\n"
  },
  {
    "path": ".github/workflows/pypy2.yaml.disabled",
    "chars": 1154,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2020-02-04 21:40:04 +0000 (Tue, 04 Feb 2020)\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://"
  },
  {
    "path": ".github/workflows/pypy3.yaml.disabled",
    "chars": 1154,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2020-02-04 21:40:04 +0000 (Tue, 04 Feb 2020)\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://"
  },
  {
    "path": ".github/workflows/python2.7.yaml.disabled",
    "chars": 1321,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2020-02-04 21:40:04 +0000 (Tue, 04 Feb 2020)\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://"
  },
  {
    "path": ".github/workflows/python3.10.yaml",
    "chars": 1365,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2020-02-04 21:40:04 +0000 (Tue, 04 Feb 2020)\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://"
  },
  {
    "path": ".github/workflows/python3.11.yaml",
    "chars": 1365,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2020-02-04 21:40:04 +0000 (Tue, 04 Feb 2020)\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://"
  },
  {
    "path": ".github/workflows/python3.6.yaml.disabled",
    "chars": 1321,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2020-02-04 21:40:04 +0000 (Tue, 04 Feb 2020)\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://"
  },
  {
    "path": ".github/workflows/python3.7.yaml",
    "chars": 1358,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2020-02-04 21:40:04 +0000 (Tue, 04 Feb 2020)\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://"
  },
  {
    "path": ".github/workflows/python3.8.yaml",
    "chars": 1358,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2020-02-04 21:40:04 +0000 (Tue, 04 Feb 2020)\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://"
  },
  {
    "path": ".github/workflows/python3.9.yaml",
    "chars": 1358,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2020-02-04 21:40:04 +0000 (Tue, 04 Feb 2020)\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://"
  },
  {
    "path": ".github/workflows/self_hosted.yaml.disabled",
    "chars": 1294,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2020-04-10 13:31:46 +0100 (Fri, 10 Apr 2020)\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://"
  },
  {
    "path": ".github/workflows/semgrep-cloud.yaml",
    "chars": 1503,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/semgrep.yaml",
    "chars": 1592,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/shellcheck.yaml",
    "chars": 1456,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/sonarcloud.yaml",
    "chars": 1193,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2023-04-14 23:53:43 +0100 (Fri, 14 Apr 2023)\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://"
  },
  {
    "path": ".github/workflows/sync_to_adjacent_repos.sh",
    "chars": 1900,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2020-02-13 15:36:35 +0000 (Thu, 13 Feb 2"
  },
  {
    "path": ".github/workflows/trivy.yaml",
    "chars": 1437,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2022-02-02 11:27:37 +0000 (Wed, 02 Feb 2022)\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://"
  },
  {
    "path": ".github/workflows/trivy_image.yaml",
    "chars": 1512,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2022-02-02 11:27:37 +0000 (Wed, 02 Feb 2022)\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://"
  },
  {
    "path": ".github/workflows/ubuntu.yaml",
    "chars": 1942,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/ubuntu_14.04.yaml.disabled",
    "chars": 1916,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/ubuntu_16.04.yaml.disabled",
    "chars": 1916,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/ubuntu_18.04.yaml.disabled",
    "chars": 1916,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/ubuntu_20.04.yaml",
    "chars": 1953,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/ubuntu_22.04.yaml",
    "chars": 1953,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/ubuntu_github.yaml",
    "chars": 1933,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/url_links.yaml.disabled",
    "chars": 1298,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2022-01-26 14:10:12 +0000 (Wed, 26 Jan 2022)\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://"
  },
  {
    "path": ".github/workflows/validate.yaml",
    "chars": 1426,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/xml.yaml",
    "chars": 1306,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".github/workflows/yaml.yaml",
    "chars": 1501,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: Tue Feb 4 09:53:28 2020 +0000\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://github.com/Hari"
  },
  {
    "path": ".gitignore",
    "chars": 87733,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2012-06-24 22:03:34 +0000 (Sun, 24 Jun 2012)\n#\n#  vim: filetype=conf\n#\n\n# ============"
  },
  {
    "path": ".gitlab-ci.yml",
    "chars": 815,
    "preview": "#  vim:ts=2:sts=2:sw=2:et\n#\n#  Author: Hari Sekhon\n#  Date: Sun Feb 23 19:02:10 2020 +0000\n#\n#  https://github.com/HariS"
  },
  {
    "path": ".gitmodules",
    "chars": 0,
    "preview": ""
  },
  {
    "path": ".hound.yml",
    "chars": 746,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2020-09-23 10:28:21 +0100 (Wed, 23 Sep 2020)\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://"
  },
  {
    "path": ".mdl.rb",
    "chars": 1148,
    "preview": "#!/usr/bin/env ruby\n#  vim:ts=4:sts=4:sw=4:et:filetype=ruby\n#\n#  Author: Hari Sekhon\n#  Date: 2024-08-22 01:58:12 +0200 "
  },
  {
    "path": ".mdlrc",
    "chars": 109,
    "preview": "mdlrc_dir = File.expand_path('..', __FILE__)\n\nstyle_file = File.join(mdlrc_dir, '.mdl.rb')\n\nstyle style_file\n"
  },
  {
    "path": ".pre-commit-config.yaml",
    "chars": 2246,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2024-08-08 17:34:56 +0300 (Thu, 08 Aug 2024)\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https///"
  },
  {
    "path": ".pylintrc",
    "chars": 21999,
    "preview": "#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2006-06-28 23:25:09 +0100 (Wed, 28 Jun 2006)\n#\n#  https://gi"
  },
  {
    "path": ".scrutinizer.yml",
    "chars": 660,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2020-03-17 11:41:13 +0000 (Tue, 17 Mar 2020)\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://"
  },
  {
    "path": ".semaphore/semaphore.yml",
    "chars": 4802,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2020-03-16 14:02:53 +0000 (Mon, 16 Mar 2020)\n#\n#  vim:ts=2:sts=2:sw=2:et\n#\n#  https://"
  },
  {
    "path": ".sonarcloud.properties",
    "chars": 37,
    "preview": "sonar.host.url=https://sonarcloud.io\n"
  },
  {
    "path": ".sonarlint/connectedMode.json",
    "chars": 97,
    "preview": "{\n    \"sonarCloudOrganization\": \"harisekhon\",\n    \"projectKey\": \"HariSekhon_DevOps-Bash-tools\"\n}\n"
  },
  {
    "path": ".terraformignore",
    "chars": 900,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2020-09-24 17:08:01 +0100 (Thu, 24 Sep 2020)\n#\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  https://"
  },
  {
    "path": ".trivyignore",
    "chars": 55,
    "preview": "#aws-access-key-id\n#aws-account-id\ngcp-service-account\n"
  },
  {
    "path": ".zlogin",
    "chars": 643,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2020-03-13 18:58:03 +0000 (Fri, 13 Mar 2"
  },
  {
    "path": ".zlogout",
    "chars": 644,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2020-03-13 18:58:03 +0000 (Fri, 13 Mar 2"
  },
  {
    "path": ".zprofile",
    "chars": 447,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2006-06-28 23:25:09 +0100 (Wed, 28 Jun 2006)\n#  (forked from .bash_profile)\n\n# ======="
  },
  {
    "path": ".zshenv",
    "chars": 727,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2020-03-13 18:58:03 +0000 (Fri, 13 Mar 2"
  },
  {
    "path": ".zshrc",
    "chars": 7504,
    "preview": "#!/usr/bin/env bash\n#  shellcheck disable=SC1091\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2006-06-28 "
  },
  {
    "path": "DOCKER_STATUS.md",
    "chars": 18133,
    "preview": "# Docker Status Page\n\ngenerated by `docker_generate_status_page.sh` in [HariSekhon/DevOps-Bash-tools](https://github.com"
  },
  {
    "path": "Gemfile",
    "chars": 917,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2022-05-13 15:25:18 +0100 (Fri, 13 May 2022)\n#\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  https://"
  },
  {
    "path": "Jenkinsfile",
    "chars": 2269,
    "preview": "//  vim:ts=4:sts=4:sw=4:et:filetype=groovy:syntax=groovy\n//\n//  Author: Hari Sekhon\n//  Date: 2017-06-28 12:39:02 +0200 "
  },
  {
    "path": "LICENSE",
    "chars": 1051,
    "preview": "Copyright 2016 Hari Sekhon\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this softwar"
  },
  {
    "path": "Makefile",
    "chars": 12907,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2016-01-17 12:56:53 +0000 (Sun, 17 Jan 2016)\n#\n#  vim:ts=4:sts=4:sw=4:noet\n#\n#  https:"
  },
  {
    "path": "Makefile.in",
    "chars": 28959,
    "preview": "#\n#  Author: Hari Sekhon\n#  Date: 2013-02-03 10:25:36 +0000 (Sun, 03 Feb 2013)\n#\n#  https://github.com/HariSekhon/DevOps"
  },
  {
    "path": "README.md",
    "chars": 226651,
    "preview": "# Hari Sekhon - DevOps Bash Tools\n\n[![GitHub stars](https://img.shields.io/github/stars/harisekhon/devops-bash-tools?log"
  },
  {
    "path": "STARCHARTS.md",
    "chars": 16884,
    "preview": "# GitHub StarCharts\n\n![Original Repos](https://img.shields.io/badge/Repos-20-blue?logo=github)\n![Stars](https://img.shie"
  },
  {
    "path": "STATUS.md",
    "chars": 68,
    "preview": "# CI/CD Status Page\n\nMoved to <https://harisekhon.github.io/CI-CD/>\n"
  },
  {
    "path": "ai/openai_api.sh",
    "chars": 2227,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#  args: /models\n#\n#  Author: Hari Sekhon\n#  Date: 2023-06-10 21:45:48 +01"
  },
  {
    "path": "applescript/app_names.sh",
    "chars": 777,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2024-11-18 17:03:28 +0400 (Mon, 18 Nov 2"
  },
  {
    "path": "applescript/browser_close_tab.scpt",
    "chars": 1843,
    "preview": "#!/usr/bin/env osascript\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2022-02-28 13:05:26 +0000 (Mon, 28 "
  },
  {
    "path": "applescript/browser_get_default.scpt",
    "chars": 1055,
    "preview": "#!/usr/bin/env osascript\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2022-02-28 13:05:26 +0000 (Mon, 28 "
  },
  {
    "path": "applescript/com.harisekhon.wakeup_script.plist",
    "chars": 501,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "applescript/get_application_names.scpt",
    "chars": 1692,
    "preview": "#!/usr/bin/env osascript\n--  vim:ts=4:sts=4:sw=4:et\n--\n--  Author: Hari Sekhon\n--  Date: 2024-10-13 20:26:31 +0300 (Sun,"
  },
  {
    "path": "applescript/get_frontmost_process.scpt",
    "chars": 571,
    "preview": "#!/usr/bin/env osascript\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2022-02-28 13:05:26 +0000 (Mon, 28 "
  },
  {
    "path": "applescript/get_frontmost_process_title.scpt",
    "chars": 1075,
    "preview": "#!/usr/bin/env osascript\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2022-12-05 16:30:05 +0000 (Mon, 05 "
  },
  {
    "path": "applescript/get_mouse_coordinates.scpt",
    "chars": 765,
    "preview": "#!/usr/bin/env osascript\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2020-06-13 20:43:57 +0100 (Sat, 13 "
  },
  {
    "path": "applescript/get_mouse_coordinates.sh",
    "chars": 91,
    "preview": "#!/usr/bin/env bash\n\nset -euo pipefail\n[ -n \"${DEBUG:-}\" ] && set -x\n\nMouseTools -location\n"
  },
  {
    "path": "applescript/is_screen_locked.py",
    "chars": 1093,
    "preview": "#!/usr/bin/env python3\n#  coding=utf-8\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2022-12-05 22:03:56 +"
  },
  {
    "path": "applescript/is_screensaver_running.scpt",
    "chars": 787,
    "preview": "#!/usr/bin/env osascript\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2022-12-05 17:44:03 +0000 (Mon, 05 "
  },
  {
    "path": "applescript/keystrokes.sh",
    "chars": 2609,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2020-06-14 17:16:31 +0100 (Sun, 14 Jun 2"
  },
  {
    "path": "applescript/mouse_clicks.scpt",
    "chars": 1267,
    "preview": "#!/usr/bin/env osascript\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2020-06-13 20:47:12 +0100 (Sat, 13 "
  },
  {
    "path": "applescript/mouse_clicks.sh",
    "chars": 3093,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2020-06-14 17:16:31 +0100 (Sun, 14 Jun 2"
  },
  {
    "path": "applescript/mouse_clicks_remote_desktop.sh",
    "chars": 1680,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2024-12-06 10:55:58 +0700 (Fri, 06 Dec 2"
  },
  {
    "path": "applescript/mouse_random_movements.sh",
    "chars": 2330,
    "preview": "#!/usr/bin/env bash\n#  vim:ts=4:sts=4:sw=4:et\n#\n#  Author: Hari Sekhon\n#  Date: 2024-12-06 08:09:48 +0700 (Fri, 06 Dec 2"
  }
]

// ... and 1604 more files (download for full content)

About this extraction

This page contains the full source code of the HariSekhon/DevOps-Bash-tools GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 1804 files (4.8 MB), approximately 1.3M tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!